【问题标题】:Create object of type specified in a string创建字符串中指定类型的对象
【发布时间】:2018-05-19 14:14:57
【问题描述】:

我有一堆由 EF 生成的类,它们是简单的表并且具有相似的结构:

public class Contact
{
    public int ID { get; set; }
    public string Description { get; set; }
}

public class Member
{
    public int ID { get; set; }
    public string Description { get; set; }
}

我还有一个返回指定类型对象的方法:

public T GetInstance<T>(string type)
{
    return (T)Activator.CreateInstance(Type.GetType(type));
}

我想做的是这样的:

public ActionResult GetAll(string ClassType)        // ClassType will be the name of one of the classes above
{
    Object LookupType = GetInstance<Object>(ClassType);

    List<LookupType> AllList = new List<LookupType>();

    AllList = repo.GetAll<LookupType>().ToList<LookupType>();    // some generic method that will return a list;
}

这让编译器发疯,因为我使用变量 (LookupType) 而不是真正的类型来构建列表。但是,这些都不起作用:

List<LookupType.GetType()> Items = new List<LookupType.GetType()>();
List<typeof(LookupType)> Items = new List<typeof(LookupType)>();

两者都会导致错误 - “使用泛型类型 List 需要 1 个类型参数”。

有没有合适的方法来做到这一点?有没有办法直接将 ClassType 转换为类型,而无需先使其成为对象(我希望从中派生类型)?

【问题讨论】:

    标签: c# class generics types


    【解决方案1】:

    尝试使用CreateInstance 方法

    SomeObject someObject = new SomeObject();
    Type type = someObject.GetType();
    
    Type listType = typeof(List<>).MakeGenericType(new [] { type });
    IList list = (IList)Activator.CreateInstance(listType);
    

    【讨论】:

    • 谢谢 - IList 不会删除它,因为它不能在 EF lambda 查询中使用它。
    【解决方案2】:

    你不能用 C# 做到这一点! 编译器必须知道参数类型。 在这方面,也许你想完成,接口会帮助你

    public class Contact: IIdDescription
    {
            public int ID { get; set; }
            public string Description { get; set; }
    }
    
    public class Member: IIdDescription
    {
         public int ID { get; set; }
         public string Description { get; set; }
    }
    
    public interface IIdDescription
    {
         int ID { get; set; }
         string Description { get; set; }
    }
    
    
    
    public ActionResult GetAll(string type)         
    {
       var AllList = new List<IIdDescription>();
    
       if(type == Member.GetType().Name)
          AllList = repo.Set<Member>().Cast<IIdDescription >().ToList();
       if(type == Contact.GetType().Name)
           AllList = repo.Set<Contact>().Cast<IIdDescription >().ToList();
    
       ...
    }
    

    并在您的视图中使用接口作为模型,例如

     @model IEnumerable<IIdDescription>
    

    【讨论】:

    • 拥有一个 case 语句(或多个 If-thens)正是我想要避免的。
    • 进入你的仓库 DbContext 你应该创建一个 Dictionary> 其中 TEntity:class 并将其用作 AllList = repo.MyDict[type].ToList().Cast ()
    【解决方案3】:

    如果您不提前知道类型,则使用动态对象列表可能会有所帮助。

        var item = GetInstance<Contact>("Namespace.Contact");
        var items = new List<dynamic>();
    
        items.Add(item);
    

    然后您可以像这样访问类型...

    Contact contact = items[0];
    

    请注意,使用动态可能会很昂贵。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-18
      • 1970-01-01
      • 2015-06-14
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多