如果我有一个动态对象或匿名对象,其结构与强类型对象的结构完全匹配,是否有.NET方法从动态对象构建一个类型化对象?
我知道我可以使用LINQ dynamicList.Select(dynamic => new Typed { .... }
类型的东西,或者我可以使用Automapper,但我想知道是否没有专门为此构建的东西?
答案 0 :(得分:42)
您可以序列化为中间格式,然后立即对其进行反序列化。这不是最优雅或最有效的方式,但它可能会完成你的工作:
假设这是你的班级:
// Typed definition
class C
{
public string A;
public int B;
}
这是你的匿名实例:
// Untyped instance
var anonymous = new {
A = "Some text",
B = 666
};
您可以将匿名版本序列化为中间格式,然后再将其反序列化为类型版本。
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(anonymous);
var c = serializer.Deserialize<C>(json);
请注意,只要往返是同步的,理论上就可以使用任何串行器/解串器(XmlSerializer,二进制序列化,其他json库)。
答案 1 :(得分:12)
您的问题归结为以下问题:我可以将一个静态类型变量转换为另一个静态类型变量(来自不同继承链的)强>)?,答案显然是否。
为什么你的问题归结为上述问题?
因此,事实上,您的代码正在处理分配给Object的静态类型值,并在编译时被视为Dynamic。因此,唯一可以将一个静态类型值转换为另一个[无反射]的情况是它们是同一继承链的一部分。否则,您必须明确地使用反射(由您编写)或隐式使用(由MS编写并使用动态用法)。
换句话说,只有当分配给动态的值是Person的基础或派生类型(为示例发明)时,以下代码才有效:
dynamic dPerson = GetDynamicPerson();
Person thePerson = (Person)dPerson;
这就是它。
公平地说,您可以使用不安全的代码访问内存地址(如C ++)逐字节复制值,但对我而言,这并不比反射更好。
答案 2 :(得分:4)
这里我们可以将匿名对象转换为Dictionary
Dictionary<string, object> dict =
obj.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(obj, null));
您也可以使用LINQ
来投射对象List<MyType> items = anonymousType.Select(t => new MyType(t.Some, t.Other)).ToList();
答案 3 :(得分:1)
如果您的对象继承自MarshalByRefObject,则可以使用RealProxy。
另一种选择是使用Reflection,但您可能受到未标记为虚拟和/或必须使用接口的内容的限制。您也可以让它复制值,假设属性是可写的,空构造函数适用于您的情况。
你问题的实际答案是否定的,没有自动方法将动态对象视为特定类型,除非它是该类型的实例,也没有任何自动工具可以从动态/匿名中复制值将对象转换为命名类的实例。
运行时不知道构造函数中发生了什么或类是如何在内部实现的,因此任何此类工具都会将类型安全性从水中吹走。动态的全部意义是允许duck typing / runtime dispatch / etc.
编辑:如果我误解了这个问题让我知道,但我假设你想把动态对象看作是SomeType的一个实例。
在我自己的项目中,我使用了一个Object Mapper类,它匹配可写属性和相同或强制类型的属性名称,所以至少我不需要写10,000行样板文件,尽管我的源不是动态的,所以我使用Reflection.Emit / DynamicMethod来大大加快它的速度。