2012-07-05 90 views
3

我有下面的代码:我如何将动态字典值转换为列表?

List<Type> p1 = new List<Type>(); 
p1.Add(typeof(int)); 
p1.Add(typeof(string)); 
dynamic genericDic = typeof(Dictionary<, >); 
dynamic specificDic1 = genericDic.MakeGenericType(p1.ToArray()); 
dynamic dic1 = Activator.CreateInstance(specificDic1); 
dic1.Add(1, "John"); 
dic1.Add(2, "Smith"); 
dynamic genericLst = typeof(List<>); 
dynamic specificLst = genericLst.MakeGenericType(typeof(string)); 
dynamic list = Activator.CreateInstance(specificLst); 
list.AddRange(dic1.Values.ToList()); 

当我尝试执行list.AddRange(dic1.Values.ToList());我得到下面的异常

公共成员“ToList”上键入'ValueCollection找不到。

堆栈跟踪:

at Microsoft.VisualBasic.CompilerServices.Symbols.Container.GetMembers(String& MemberName, Boolean ReportErrors) 
    at Microsoft.VisualBasic.CompilerServices.NewLateBinding.ObjectLateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) 
    at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) 
    at StyleResearch.DataManagement.DataStream.Business.MonthEndProcess.ConverToLegacyStructureInMemory(List`1 marketDataTypeIds, String tableName, Int32 placeHolderValue) in C:\Style Research\Work\SRDM\trunk\StyleResearch.DataManagement.DataStream.Business\MonthEndProcess.vb:line 1850 
    at StyleResearch.DataManagement.DataStream.UI.DDLMonthEndProcess._Lambda$__6(LegacyStructureDetail legacy) in C:\Style Research\Work\SRDM\trunk\StyleResearch.DataManagement.DataStream.UI\DDLMonthEndProcess.vb:line 1198 
    at System.Threading.Tasks.Parallel.<>c__DisplayClass2d`2.<ForEachWorker>b__23(Int32 i) 
    at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c() 

注:我已经VB.NET样品转化成C#,但堆栈跟踪从VB.NET工程

当我做下面的工作原理精绝:

Dictionary<int, string> dic = new Dictionary<int, string>(); 
dic.Add(1, "John"); 
dic.Add(2, "Smith"); 
List<string> lst = new List<string>(); 
lst.AddRange(dic.Values.ToList()); 

回答

2

ToList < T>()是一个扩展方法的IEnumerable < T>。但是,您的dic1.Values是动态类型不是IENumerable < string>所以.net无法找到并使用此扩展方法。您可以尝试只是简单的foreach:

foreach (var value in dic1.Values) 
    list.Add(value) 
+0

感谢您的回复,但我确实知道这种方法。想知道为什么它会失败时,我使用反射创建对象,而不是正常进行时。 – Rajesh 2012-07-05 10:44:18

+2

正如我所说的那样,因为动态类型和扩展方法(ToList)。动态不支持扩展方法(http://stackoverflow.com/questions/5311465/extension-method-and-dynamic-object-in-c-sharp) – Nikolay 2012-07-05 10:46:39

3

只投它:

list.AddRange(((IEnumerable<string>)dic1.Values).ToList()); 

此外,您还可以通过动态又来了:

list.AddRange((dynamic)dic1.Values)); 
+0

正如我所理解的使用动态和反射背后的想法是,你在编译时不知道列表中的元素的类型(IEnumerable ),所以你不能在编译时投射它。过分的,你可以使用类型列表,没有反射和动态 – Nikolay 2012-07-05 11:10:38

+0

同意 - 但他已经宣布上述类型 - 所以,在这种情况下,它是已知的。 – 2012-07-05 15:32:23

0
list.AddRange((IEnumerable<string>)dic.Values)) 

List<string> list = ((IEnumerable<string>)dic.Values).ToList(); 

List<string> list = new List<string>((IEnumerable<string>)dic.Values); 
+0

当我使用上面的代码时,我得到这个异常:没有找到类型'ValueCollection'的公共成员'Cast'。 – Rajesh 2012-07-05 10:47:47

+0

这些工作都不是: 'System.Collections.Generic.Dictionary .ValueCollection'不包含'Cast'的定义 – 2012-07-05 10:49:00

+1

@Rajesh:然后尝试System.Linq.Enumerable。铸造(输入)' – abatishchev 2012-07-05 10:49:01

0

尝试调用不带扩展功能的语法,即像

Enumerable.ToList ((dynamic) dic1.Values) 

的DLR在运行时不(由于性能原因寻找继承接口的扩展功能,或者为了避免歧义,我猜测)。