簡體   English   中英

為泛型方法傳遞具體類型參數時,返回泛型IEnumerable

[英]return generic IEnumerable when passing concrete type parameter for a generic method

此代碼示例摘自以下答案https://stackoverflow.com/a/16491759/98706

public static Boolean PurgeDataObject(this IDataObject dataObject, Guid uid)
{
    return PurgeDataObjectImpl((dynamic) dataObject, uid);
}

private static Boolean PurgeDataObjectImpl<T>(T dataObject, Guid uid)
    where T : IDataObject
{
    return DataProvider.DeleteDataObject<T>(uid, DataProvider.GetConnection());
}

我有一種類似的情況,我想在執行時根據類型返回相關的EF實體,以嘗試清理一些現有的繼承代碼,如下所示:(

區別在於我希望函數返回IEnumerable<T>

GetFilteredData不會有T的概念,所以我會遇到以下編譯錯誤: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

    private IEnumerable<T> GetFilteredData(Type entityType, SortedList<string, string> filterList, List<int> weeks)
    {
        return GetFilteredDataImpl((dynamic)entityType, filterList, weeks);
    }

    private IEnumerable<T> GetFilteredDataImpl<T>(T entityType, SortedList<string, string> filterList, List<int> weeks) where T : EntityObject
    {
        var data = _modelContext.CreateObjectSet<T>().AsExpandable();
          // do more filtering and then call .ToList() to return a List<T>
    }

如果不使用反射,則無法將Type類轉換為通用T參數。 該參數也需要作為方法的一部分出現。

喬恩·斯凱特(Jon Skeet)將示例推論與泛型結合使用,以保證類型安全並簡化泛型代碼。 不幸的是,使用Type和反射會失去類型安全性。

private IEnumerable<EntityObject> GetFilteredData(Type entityType,
                                                  SortedList<string, string> filterList,
                                                  List<int> weeks)
{
    var method = typeof(<class>).GetMethod("GetFilteredDataImpl");
    var generic = method.MakeGenericMethod(entityType);
    return (IEnumerable<EntityObject>)generic.Invoke(this, new[] { filterList, weeks });
}

private IEnumerable<T> GetFilteredDataImpl<T>(SortedList<string, string> filterList,
                                              List<int> weeks)
    where T : EntityObject
{
    var data = _modelContext.CreateObjectSet<T>().AsExpandable();
      // do more filtering and then call .ToList() to return a List<T>
}

但是,您可以創建一個對象以傳遞。

private IEnumerable<EntityObject> GetFilteredData(Type entityType, SortedList<string, string> filterList, List<int> weeks)
{
    var instance = (EntityObject)Activator.CreateInstance(entityType);
    return GetFilteredDataImpl((dynamic)instance, filterList, weeks);
}

private IEnumerable<T> GetFilteredDataImpl<T>(T entityType, SortedList<string, string> filterList, List<int> weeks) where T : EntityObject
{
    var data = _modelContext.CreateObjectSet<T>().AsExpandable();
      // do more filtering and then call .ToList() to return a List<T>
}

這仍將返回IEnumerable<EntityObject> ,但它將生成垃圾,並且您將ArgumentException換為InvalidCastException

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM