我知道现在在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
答案 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)
你不能从动态类型转换为像这样的实体类型,因为当时类型没有与动态相关而不是看起来像它具有类似的属性。
但是,您可以序列化动态实例,然后将其反序列化为您拥有的实体类型。我不确定你为什么要那样做......