2015-11-02 78 views
0

有型号Dictionary<string,dynamic>并且想将其转换为Dictionary<string, MyType1>Dictionary<string, MyOtherType>如何将动态对象转换为指定的类型?

我已经试过

var converted = (Dictionary<string,MyType1>)model 

没有成功尝试

IConvertible iConv = model; var converted = iConv.ToType(typeof(MyOtherType), null); 

太多,但它不工作

异常:无法转换System.Object要键入x

如何从运行时类型(动态)转换为众所周知的类型?

+0

看起来像这不是一个适当的动态类型的使用。这是一种静态类型。 –

+0

类型为“MyType1”的字典对象中的_all_值? –

+0

@DStanley就是这样!在检查之后......看起来像是当一个键值为空时发生异常! – Bellash

回答

3

没有从一种字典类型到另一种字典类型的内置转换。但是,使用Enumerable.ToDictionary,您可以轻松地从任何其他数据结构创建新字典。

在你的具体的例子,你可以用它作为

var converted = model.ToDictionary(kv => kv.Key, kv => (MyType1) kv.Value); 

当然,如果你的价值观是不实际MyType1型的,这将引发异常。如果它们不是,那么请在(MyType1) kv.Value之前调用一些自定义转换函数。

+0

将“as”用于与“Where(i => i.Value!= null)”结合使用时应该处理异常。 (除非涉及不可空类型,那就是) – PTwr

+0

谢谢,但我得到一个'System.InvalidCastException'类型的异常:不能从类型'System.Object'的对象类型转换为'MyType1'。' – Bellash

+0

@Bellash这就是我已经涵盖在我的问题的最后一段:我只回答你问的问题。如果您还想转换这些值,那么问题中没有足够的信息来说明该转换应该如何工作,只是需要找到某种方式来执行此转换。 – hvd

1

我会将一个静态构造函数放在您熟知的类型上,它接受dynamic,并从中构建众所周知的类型。例如

public class SomeType 
{ 
    public static SomeType FromDynamic(dynamic arg) 
    { 
     return new SomeType 
     { 
       SomeProperty = arg.SomeProp 
     } 
    } 

    public int SomeProperty {get; set; } 
} 

然后,你只需要遍历您Dictionary<string,dynamic>并建立新的对象,如:从@hvd

var dictionary = new Dictionary<string, SomeType>(); 
foreach(var item in model) 
{ 
    dictionary.Add(item.Key, SomeType.FromDynamic(item.Value)); 
} 

或者借用:

var converted = model.ToDictionary(kv => kv.Key, kv => SomeType.FromDynamic(kv.Value)); 
+1

是的,这是执行这种转换的一种有效方式。就个人而言,在这种情况下,如果你建议的改造是简单的我会把它内联写:'model.ToDictionary(KV => kv.Key,KV =>新SOMETYPE {SomeProp = kv.Value.SomeProp});' 。如果转换更复杂,那么我会用像你这样的帮助方法。 – hvd

2

以下小演示适用于简单类型: MapDynamicToDictionary测试显示将动态转换为字典。 MapDictionaryToType节目做检查类型或使用as

public class Test 
{ 
    [Fact] 
    public void MapDynamicToDictionary() 
    { 
     dynamic d = new { Nr = 1, Name = "Devon" }; 
     var dictionary = TurnObjectIntoDictionary(d); 

     Assert.Equal(2, dictionary.Keys.Count); 
    } 

    [Fact] 
    public void MapDictionaryToType() 
    { 
     dynamic d = new { Nr = 1, Name = "Devon" }; 
     var dictionary = TurnObjectIntoDictionary(d); 
     var instance = new MyType(); 
     Map(dictionary, instance); 
     Assert.Equal(instance.Nr, 1); 
     Assert.Equal(instance.Name, "Devon"); 
    } 

    public static void Map<T>(IDictionary<string, object> dictionary, T instance) 
    { 
     var attr = BindingFlags.Public | BindingFlags.Instance; 
      foreach (var prop in instance.GetType().GetProperties(attr)) 
     { 
      if (prop.CanWrite) 
      { 
       if(dictionary.ContainsKey(prop.Name)) 
       { 
        var v = Convert.ChangeType(dictionary[prop.Name], prop.PropertyType); 
        prop.SetValue(instance, v);     } 
      } 
     } 
    } 

    public static IDictionary<string, object> TurnObjectIntoDictionary(object data) 
    { 
     var attr = BindingFlags.Public | BindingFlags.Instance; 
     var dict = new Dictionary<string, object>(); 
     foreach (var prop in data.GetType().GetProperties(attr)) 
     { 
      if (prop.CanRead) 
      { 
       dict.Add(prop.Name, prop.GetValue(data, null)); 
      } 
     } 
     return dict; 
    } 
} 

class MyType 
{ 
    public int Nr { get; set; } 
    public string Name { get; set; } 
} 

能使用TypeConverter来处理更复杂的例子字典转换为T类型

你可以改善这一点。很好的例子:http://putridparrot.com/blog/type-conversions-in-c/

+0

这是一个绝妙的解决方案!它看起来不错,upvoted而问题解决了@ hvd回答 – Bellash

+0

谢谢!我在地图上添加了一个转换,所以它应该更经常地获得成功,并且可以链接到底部的其他可能性。 –

相关问题