【问题标题】:Get List<T> by its generic type T from a collection (C#)从集合中通过其泛型类型 T 获取 List<T> (C#)
【发布时间】:2016-08-24 05:50:07
【问题描述】:

我有很多 Lists 包含不同类型的对象,但所有这些类型都有一个公共基类 ModelBase。每个通用 List 类型都是唯一的,即不会有两个列表包含相同的类型。

最后,我想要一个像public List&lt;TModel&gt; GetModelList&lt;TModel&gt;() 这样的函数,它将从ModelBase 派生的任何对象的类型作为泛型类型或参数,然后返回该泛型类型的相应List&lt;TModel&gt;

我有哪些选择来实现这一目标?

我考虑过Dictionary&lt;Type, List&lt;ModelBase&gt;&gt;,但后来我将子类类型(例如AreaModel)转换为基类类型ModelBase 用于存储,反之,当我再次获取它时。我不想每次在存储之前或加载之后都强制转换列表。有没有办法简化这个?也许我们可以自动转换,因为我们正在传递我们想要的 List 类型作为参数?

【问题讨论】:

    标签: c# list generics dictionary collections


    【解决方案1】:

    只需将列表作为对象存储在内部字典中,并在需要时转换为指定的类型。尝试将列表存储为模型库列表是没有意义的,因为列表不是那种类型。

    类似这样的:

    public class Container {    
        private readonly ConcurrentDictionary<Type, object> _container = 
            new ConcurrentDictionary<Type, object>();
    
        public List<TModel> Get<TModel>() where TModel: ModelBase {
            return _container.GetOrAdd(typeof(TModel), t => new List<TModel>()) as List<TModel>;        
        }
    }
    

    我使用并发字典来确保为每种类型只创建一个列表实例。如果需要,您可以轻松添加一种方法来将现有列表存储在字典中。

    // Usage
    var container = new Container();
    var person = container.Get<Person>();
    var orders = container.Get<Order>();
    

    【讨论】:

    • 查看 MSDN,ConcurrentDictionary 仅与线程安全相关,但我并不真正需要它。为什么您选择它而不是普通字典还有其他区别吗?我真的不明白您所说的“确保为每种类型只创建一个列表实例”是什么意思——这与普通字典的情况是否相同?
    • 如果我可以通过像使用 ConcurrentDictionary 而不是普通字典这样简单的方法使我自己的类线程安全,那么我会的。是的,如果你只在单线程环境中使用它,那么普通的字典就可以正常工作,但你不会有方便的.GetOrAdd(..) 方法。
    【解决方案2】:

    怎么样

    public List<Person> GetPersons()
    {
         var table = context.ExecutDataTable();
         return GetModelList<Person>(table);
    }
    
    public List<T> GetModelList<T>(DataTable table) where T : ModelBase, new()
    {        
        var list = new List<T>();
        foreach(DataRowView row in table.DefaultView)
        {
            var item = new T();
            t.Load(row);
            list.Add(item);
        }
        return list;
    }
    

    或者您可以使用Cast 扩展方法。如果您的数据层中有一个始终返回 List&lt;ModelBase&gt; 的方法,但您确定您的列表仅包含 Person 对象,则此解决方案很有意义

    public List<Person> GetPersonList()
    {
        // returns a List<ModelBase>
        var persons = context.ExecuteList("SELECT * FROM person");
        return persons.Cast<Person>().ToList();
    }
    

    【讨论】:

      【解决方案3】:

      还有其他方法可以归档你想要的结果,你可以创建一个静态类:

      static class Store<TModel> where TModel : ModelBase
      {
          public static readonly List<TModel> List = new List<TModel>();
      }
      

      这样你就有了每个Store&lt;T&gt; 的列表。 另一种方法是使用Monostate Pattern

      class Store2<TModel> where TModel : ModelBase
      {
          static readonly List<TModel> list = new List<TModel>();
          public List<TModel> List { get { return list; } }
      }
      

      那么你可以这样使用它:

      var storeA = new Store<ModelA>();
      storeA.List.Add(new ModelB());
      
      var storeB = new Store<ModelB>();
      storeB.List.Add(new ModelB());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-23
        • 2012-11-28
        • 1970-01-01
        • 1970-01-01
        • 2021-09-26
        • 2022-12-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多