带有 ExpandoObject 的动态关键字附加和删除属性

dynamic keyword with ExpandoObject to attach and remove properties

我知道现在在 C# 3.0 中我们可以在 运行 时间内对 add/remove 属性使用动态关键字,就像对象作为通用容器的 JavaScript 概念一样,但我有一个问题。

真的展开我想要的类型的对象吗??

例如: 我们有 class:

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

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

        dynamic p = new ExpandoObject();

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

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

An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll

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

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

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

  • 转换:改变指向的引用类型的行为 一个东西。向上或向下移动对象层次结构或移动到 实现接口

  • Converting: 从原始源对象创建新对象 不同的类型并通过对该类型的引用访问它。

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