【问题标题】:Generic method of type <T> at runtime AND storing result in IEnumerable<T><T> 类型的通用方法在运行时并将结果存储在 IEnumerable<T> 中
【发布时间】:2014-07-20 02:22:13
【问题描述】:

在将其标记为重复之前,请注意我已阅读所有这些问题,包括 Jon Skeet 的回答,但我仍然有问题。 我已经浏览过的链接,还有一些我没有在这里列出:

Instantiate object with reflection and dynamic arguments count

Instructing a generic to return an object of a dynamic type

Is there a way not to use dynamic when instantiating a type that inherits from generic?

我搜索了同一个问题,并意识到在运行时提供类型 T 是不可能的,因为在编译时必须知道泛型类型 T。我明白这一点,但我有以下情况:

基本上我想这样做:

public IEnumerable<T> GetListing<T>(string entityName)
{
    Entity entity = new Entity { Name = entityName, Action = "Select" };

    ResponsePacket<T> entityViewModel = new ResponsePacket<T>();

    entityViewModel.Records = myHttpClient.GetAllEntities<T>(entity, "10", "0").Content;

    return entityViewModel.Records.AsEnumerable();
}

然后这样称呼它:

public IEnumerable<myType> CallListing(string entityName)
{
    Type myType = {get type of entityName through some method eg User}
    IEnumerable<myType> result = GetListing<myType>;
    return result;
}

现在我读到这 无法 没有反射 实现,这意味着我必须创建一个 GetListing&lt;&gt; 的实例,然后通过关于 @987654327 的反射告诉它@。

我的问题是即使我使用反射创建GetListing&lt;myType&gt;的实例并在运行时通过反射调用它,如何在IEnumerable&lt;myType&gt;中得到GetListing&lt;T&gt;的返回结果?反射也会在运行时提供IEnumerable&lt;myType&gt; 的结果吗?

据我所知,Reflection 的返回结果是一个对象,我如何将其转换为 IEnumerable&lt;myType&gt;,我无法将其转换为 IList,如下所示:

IList returnedresult = (IList)returnedResult 因为 我的 Grid/View 页面需要 IEnumerable&lt;myType&gt; 的模型,即 IEnumerable&lt;User&gt;IEnumerable&lt;Roles&gt; 我希望通过反射得到。我必须将模型传递给我的视图@model IEnumerable&lt;GridModel&gt;,其中gridmodel 需要IEnumerable&lt;myType&gt;

我也读过 dynamic 是去这里的方式,但我不知道如何。我将如何使用动态实现我正在寻找的东西?我没有任何线索。请告诉我是否有办法将反射方法的返回结果存储在IEnumerable&lt;myType&gt; 中。

如果这两个都不能实现,那么请告诉我如何以其他方式实现。

我在编译时不知道实体的类型,否则会有很多代码复制,如果我有 100 个要为其调用 GetListing() 的实体,我将不得不编写 GetUserListing、GetRolesListing、Get.. .Listing() 然后我必须从 GetUserListing、GetRolesListing 方法内部显式调用 GetListing&lt;User&gt;GetListing&lt;Roles&gt;,这违背了目的。

【问题讨论】:

  • "我的 Grid/View 页面需要一个 IEnumerable 的模型" 为什么会这样?如果您在编译时不知道类型,那么拥有通用 IEnumerable 的页面有什么好处?
  • IEnumerable 即 IEnumerable 或 IEnumerable 如果我能够将其存储在 IEnumerable 中,我将通过反映的返回结果获得。
  • 你能在调用CallListing之前计算出entityName的类型吗?
  • @zeppelin 对,我的问题是,如果您不知道编译时类型将是 User,为什么最终需要 IEnumerable&lt;User&gt; 而不仅仅是 IEnumerable ?
  • 锻炼是什么意思?我希望通过字符串获取实体的类型,entityName="User" 或 "Role" 将由用户在运行时提供。例如我会得到“用户”,然后我会尝试将字符串“用户”转换为用户类型,这个类型将存储在 myType 变量中,其数据类型将为 Type。然后我想把它传递给 GetListing.

标签: c# generics dynamic reflection


【解决方案1】:

我认为这就是你所关心的:

void Main()
{
    Console.WriteLine(Get<int>("System.Int32").ToString());
    Console.WriteLine(Get<string>("System.String").ToString());
    Console.WriteLine(Get<double>().ToString());
    Console.WriteLine(Get<long>().ToString());
}

public Type TypeResolver(string type)
{
    return Type.GetType(type);
}

public IEnumerable<T> Get<T>(string typeName)
{   
    var type = TypeResolver(typeName);
    var entityStore = new EntityStore();
    return entityStore.GetType().GetMethod("GetAll").MakeGenericMethod(type).Invoke(entityStore, null) as IEnumerable<T>;
}

public IEnumerable<T> Get<T>()
{
    var entityStore = new EntityStore();
    return entityStore.GetType().GetMethod("GetAll").MakeGenericMethod(typeof(T)).Invoke(entityStore, null) as IEnumerable<T>;
}

public class EntityStore
{
    public IEnumerable<T> GetAll<T>()
    {
        return new List<T>();
    }
}

【讨论】:

  • 在您的 Main() 方法中,您在编译时传递 ,并根据这些类型调用相应的 GetAll() 方法,但在我的问题中,我不知道类型,例如,如果我有用户,我想调用 Get。我认为在您的示例 Get 中,Get 与编写 GetListing 或 GetListing 相同,这是不可能的,因为我在编译时不知道类型。否则会有太多的 switch case 语句,我必须列出所有可能被调用的类型。
  • if(entityName=="User"){Console.WriteLine(Get("Models.User").ToString());}else if(...){ 控制台。 WriteLine(Get("Models.Roles").ToString());} else if(..){ ...} else if(...){ Get<..> }。这意味着我必须像这样列出每个模型,我不想这样做,我不知道编译时的类型。
  • 这只是向您展示它有效。在你说它不起作用之前先尝试一下代码。
  • 实际上我花了一些时间才回复您的帖子,因为我想自己尝试您的代码,我尝试过,然后在这里回复。请阅读我上面的 cmets 并告诉我是否误解了给定的代码,因为我真的不知道,我试过了,请阅读我上面的两个 cmets 并告诉我我哪里错了。
  • 那你问的是不可能的。 C#不做方法的动态分派,你需要知道编译时调用了哪个方法的重载。这包括泛型。仅仅因为您通常在 Visual Studio 中看不到 部分并不意味着它不存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
相关资源
最近更新 更多