使用ExpandoObject的dynamic关键字来附加和删除属性

时间:2015-07-03 15:21:18

标签: c# .net dynamic c#-3.0

我知道现在在C#3.0中我们可以使用dynamic关键字在运行时添加/删除属性,就像Object作为通用容器的JavaScript概念一样,但我有一个问题。

它真的扩展了我想要的类型的对象吗?

例如: 我们上课了:

    class Person
{
    public string Name { get; set; }
    public int Age { get; set;}
}

我将从Person Class创建一个新对象:

        dynamic p = new ExpandoObject();

现在这个对象真的是Person类的对象吗?它不再与人类相关了?

Console.WriteLine(p.GetType()); // System.Dynamic.ExpandoObject

现在我将设置属性值并使用新属性展开对象p' Foo':

        p.Age = 25;
        p.Foo = "foo"; 

我附上了新物业' Foo'并设定财产的价值'年龄'但是我为System.Dynamic.ExpandoObject类型的对象而不是Person类型的对象这样做,所以我在这部分不匹配,我真的从我需要的类型扩展对象,我可以使用强制转换来引用像这样的对象类型:

Console.WriteLine(((Person)p).Name);  
  

未处理的类型异常   ' Microsoft.CSharp.RuntimeBinder.RuntimeBinderException'发生在   System.Core.dll

2 个答案:

答案 0 :(得分:2)

我认为你在这里混淆铸造和转换的问题。

  • 投射:更改指向的引用类型的行为 一个东西。向上或向下移动对象层次结构或向上移动 已实施的界面

  • 转换:从原始源对象创建新对象 一种不同的类型,并通过对该类型的引用来访问它。

通常很难知道C#中2的区别,因为它们都使用相同的C#运算符:强制转换。

在这种情况下,你几乎肯定不会寻找演员表演。将动态转换为另一个动态本质上是一种身份转换。它没有提供任何价值,因为您只是将动态引用返回到同一个底层对象。由此产生的查找将没有什么不同。

相反,您在此方案中看起来需要的是转换。这是将底层对象变形为不同类型并以动态方式访问结果对象。最好的API是Convert.ChangeType

public static dynamic Convert(dynamic source, Type dest) {
  return Convert.ChangeType(source, dest);
}

在这种情况下,而不是:

Console.WriteLine(((Person)p).Name);  

尝试:

Console.WriteLine(ConvertTo<Person>(p).Name);  

如果您愿意,我可以写ConvertTo<T>声明并在此解释。

答案 1 :(得分:1)

你不能从动态类型转换为像这样的实体类型,因为当时类型没有与动态相关而不是看起来像它具有类似的属性。

但是,您可以序列化动态实例,然后将其反序列化为您拥有的实体类型。我不确定你为什么要那样做......