如何从动态对象转换为指定的Type?

时间:2015-11-02 13:22:15

标签: c# casting type-conversion

拥有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

类型

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

3 个答案:

答案 0 :(得分:3)

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

在您的特定示例中,您可以将其用作

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

当然,如果您的值实际上不是MyType1类型,则会抛出异常。如果不是,则代替(MyType1) kv.Value,在此时调用一些自定义转换函数。

答案 1 :(得分:2)

以下小型演示适用于简单类型: MapDynamicToDictionary测试显示将动态变为字典。 MapDictionaryToType显示将字典转换为T类型。

您可以通过检查类型或使用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来处理更复杂的示例。很好的例子:http://putridparrot.com/blog/type-conversions-in-c/

答案 2 :(得分:1)

我会在你熟知的类型上放置一个静态构造函数,它接受s = s .replace("`%rackname`", rName) .replace("`%compname`", compName) .replace("`%sysname`", sysName); ,并从中构建一个众所周知的类型。 e.g。

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