Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
获取列表<;T>;通过集合(C#)中的泛型类型T_C#_List_Generics_Dictionary_Collections - Fatal编程技术网

获取列表<;T>;通过集合(C#)中的泛型类型T

获取列表<;T>;通过集合(C#)中的泛型类型T,c#,list,generics,dictionary,collections,C#,List,Generics,Dictionary,Collections,我有许多列表包含不同类型的对象,但所有这些类型都有一个公共基类ModelBase。每个通用列表类型都是唯一的,即不会有两个包含相同类型的列表 最后,我希望有一个类似于public List GetModelList()的函数,它将从ModelBase派生的任何对象的类型作为泛型类型或参数,然后返回该泛型类型的相应List 要实现这一目标,我有哪些选择 我曾考虑使用字典,但后来我将子类类型(例如AreaModel)转换为基类类型ModelBase,用于存储,反之亦然,当我再次获取它时。我不想每次存

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

最后,我希望有一个类似于
public List GetModelList()
的函数,它将从
ModelBase
派生的任何对象的类型作为泛型类型或参数,然后返回该泛型类型的相应
List

要实现这一目标,我有哪些选择


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

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

大概是这样的:

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>;        
    }
}
var storeA = new Store<ModelA>();
storeA.List.Add(new ModelB());

var storeB = new Store<ModelB>();
storeB.List.Add(new ModelB());
公共类容器{
专用只读ConcurrentDictionary _容器=
新的ConcurrentDictionary();
public List Get(),其中TModel:ModelBase{
返回_container.GetOrAdd(typeof(TModel),t=>newlist())作为列表;
}
}
我使用并发字典来确保每个类型只创建一个列表实例。如果需要,您可以轻松添加一个方法来在字典中存储现有列表

// Usage
var container = new Container();
var person = container.Get<Person>();
var orders = container.Get<Order>();
//用法
var container=新容器();
var person=container.Get();
var orders=container.Get();

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

大概是这样的:

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>;        
    }
}
var storeA = new Store<ModelA>();
storeA.List.Add(new ModelB());

var storeB = new Store<ModelB>();
storeB.List.Add(new ModelB());
公共类容器{
专用只读ConcurrentDictionary _容器=
新的ConcurrentDictionary();
public List Get(),其中TModel:ModelBase{
返回_container.GetOrAdd(typeof(TModel),t=>newlist())作为列表;
}
}
我使用并发字典来确保每个类型只创建一个列表实例。如果需要,您可以轻松添加一个方法来在字典中存储现有列表

// Usage
var container = new Container();
var person = container.Get<Person>();
var orders = container.Get<Order>();
//用法
var container=新容器();
var person=container.Get();
var orders=container.Get();
那怎么办

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;
}
那怎么办

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;
}

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

static class Store<TModel> where TModel : ModelBase
{
    public static readonly List<TModel> List = new List<TModel>();
}
静态类存储,其中TModel:ModelBase
{
公共静态只读列表=新列表();
}
这样,您就有了每个
存储的列表。
另一种方法是使用:

class Store2,其中TModel:ModelBase
{
静态只读列表=新列表();
公共列表{get{return List;}}
}
然后你可以这样使用它:

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>;        
    }
}
var storeA = new Store<ModelA>();
storeA.List.Add(new ModelB());

var storeB = new Store<ModelB>();
storeB.List.Add(new ModelB());
var storeA=newstore();
storeA.List.Add(newmodelb());
var storeB=新存储();
添加(newmodelb());

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

static class Store<TModel> where TModel : ModelBase
{
    public static readonly List<TModel> List = new List<TModel>();
}
静态类存储,其中TModel:ModelBase
{
公共静态只读列表=新列表();
}
这样,您就有了每个
存储的列表。
另一种方法是使用:

class Store2,其中TModel:ModelBase
{
静态只读列表=新列表();
公共列表{get{return List;}}
}
然后你可以这样使用它:

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>;        
    }
}
var storeA = new Store<ModelA>();
storeA.List.Add(new ModelB());

var storeB = new Store<ModelB>();
storeB.List.Add(new ModelB());
var storeA=newstore();
storeA.List.Add(newmodelb());
var storeB=新存储();
添加(newmodelb());

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