我想要一个将字符串映射到不同类型的通用列表的Dictionary。即以下列形式:
Key Value string List<T> string List<U> string List<V> string List<U> ...
目前我正在使用Dictionary<string, IList>
,然后从每个字典KeyValuePair<string, IList> pair
条目中提取强类型列表,如下所示:
Type layerType = pair.Value.GetType().GetGenericArguments()[0];
List<layerType> objectsClicked = pair.Value as List<layerType>;
有更好的方法吗?
[编辑]
正如已经指出的那样,上面的内容并没有编译,道歉 - 这就是当你在做某些事情的同时问一个问题时所得到的。
更多解释。我正在制作一个基本的空间数据查看器。最终视图由一组Layer<T>
组成。每个图层都提供一个委托来呈现其类型(给定偏移量和比例)以及检查其对象在当前窗口中的方式。对于命中测试,我希望每个图层的列表都被击中了对象。对于List<Point>
图层,该列表将是Point
等等......来自所有Layer<T>
的点击的分组将是强类型列表的集合。
答案 0 :(得分:40)
Dictionary<string, dynamic>
假设您使用的是C#4
Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>();
Dict.Add("int", new List<int>());
Dict.Add("string", new List<string>());
Dict["int"].Add(12);
Dict["string"].Add("str");
foreach (KeyValuePair<string, dynamic> pair in Dict) {
Type T = pair.Value.GetType();
Console.WriteLine(T.GetGenericArguments()[0].ToString());
}
打印出来
System.Int32
System.String
这就是你要找的东西吗?
答案 1 :(得分:2)
使用Dictionary<string, IList>
可能只是解决方案。但是你的代码是错的,你不能使用这样的泛型。你不能像这样创建动态类型。
您需要的一般问题是它与C#等强类型语言不兼容。在强类型语言中,您必须知道什么类型是完全类型。但是不能用正常手段来完成。你对泛型的理解也是错误的。它只是该类型的编译时扩展。
一般的想法:在您的情况下,使用您保存在这些列表中的某种类型的OOP层次结构。这将是一个更好,更安全的想法,并不会让每个看着你的代码的人撕掉他的头发。
答案 2 :(得分:2)
我将采取Euphoric和Adam之间的中间地带,你应该使用IList
和dynamic
。这是我认为更正确的方法:
var dict = new Dictionary<string, IList>();
dict.Add("u", new List<U>());
dict.Add("v", new List<V>());
// in case of members you know they exist on an IList
dict["u"].Add(new U());
dict["v"].Add(new V());
// in case you know what you are going to get back, in which case you should cast
var uProperty = (dict["u"][0] as U).UProperty
var vProperty = (dict["v"][0] as V).VProperty
// in case your're not sure of
(dict[someKey] as dynamic)[someIndex].SomeMember...;
所有这些都比依靠反思简单得多。基本思想是将字典值类型声明为IList
,以使您的意图更加清晰,同时利用dynamic
来减轻反射怪物并缩短代码。
答案 3 :(得分:0)
我实际上认为更简洁的方法是为您的字典创建一个包装器:
public class GlobalStore
{
private readonly IDictionary<Type, IEnumerable> _globalStore;
public GlobalStore()
{
_globalStore = new ConcurrentDictionary<Type, IEnumerable>();
}
public IEnumerable<T> GetFromCache<T>()
where T : class
{
return (IEnumerable<T>) _globalStore[typeof(T)];
}
public void SetCache<T>(IEnumerable<T> cache)
where T : class
{
_globalStore[typeof(T)] = cache;
}
}
以下是对它的测试:
[TestClass]
public class GlobalStoreTest
{
[TestMethod]
public void GlobalStore_Test()
{
//Arrange
var globalStore = new GlobalStore();
globalStore.SetCache(new List<ClientModel>
{
new ClientModel
{
ClientId = 1,
ClientName = "Client1"
},
new ClientModel
{
ClientId = 2,
ClientName = "Client2"
}
});
//Act
var clients = globalStore.GetFromCache<ClientModel>();
//Assert
Assert.AreEqual(2, clients.Count());
}
}