dynamic关键字与ExpandoObject一起附加和删除属性

本文关键字:删除 属性 一起 关键字 ExpandoObject dynamic | 更新日期: 2023-09-27 18:01:07

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

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

例如:我们有班级:

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

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

        dynamic p = new ExpandoObject();

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

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

现在我将为属性设置值,并用新属性"Foo"扩展对象p:

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

我附加了新的属性"Foo",并为属性"Age"设置了值,但我为System.Dynamic.ExpandoObject类型的对象而不是Person类型的对象这样做,所以我在这部分不匹配,我真的从我需要的类型扩展了对象吗,我可以使用强制转换来指代这样的对象类型吗:

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

类型为的未处理异常中出现"Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"System.Core.dll

dynamic关键字与ExpandoObject一起附加和删除属性

我认为您混淆了这里的强制转换和转换问题。

  • 铸造:更改指向一个物体。向上或向下移动对象层次结构,或移动到实现接口

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

通常很难知道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>声明并在这里解释。

您不能像这样从动态类型强制转换为实体类型,因为该类型当时与动态无关,只是看起来像它,因为它具有类似的属性。

但是,您可以序列化动态实例,然后将其反序列化为您所拥有的实体类型。我不知道你为什么要这么做。。。