有没有办法将动态或匿名对象转换为强类型的声明对象?

Pro*_*ofK 37 .net anonymous-class dynamicobject c#-4.0

如果我有一个动态对象或匿名对象,其结构与强类型对象的结构完全匹配,是否有.NET方法从动态对象构建类型化对象?

我知道我可以使用LINQ dynamicList.Select(dynamic => new Typed { .... }类型的东西,或者我可以使用Automapper,但我想知道是否没有专门为此构建的东西?

Gri*_*air 46

您可以序列化为中间格式,然后立即对其进行反序列化.这不是最优雅或最有效的方式,但它可能会完成您的工作:

假设这是你的班级:

// Typed definition
class C
{
    public string A;
    public int B;
}
Run Code Online (Sandbox Code Playgroud)

这是你的匿名实例:

// Untyped instance
var anonymous = new {
    A = "Some text",
    B = 666
};
Run Code Online (Sandbox Code Playgroud)

您可以将匿名版本序列化为中间格式,然后再将其反序列化为类型版本.

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(anonymous);
var c = serializer.Deserialize<C>(json);
Run Code Online (Sandbox Code Playgroud)

请注意,只要往返是同步的,理论上这对于任何串行器/解串器(XmlSerializer,二进制序列化,其他json库)都是可能的.

  • 一直在考虑这个问题:我猜你总是会有一个中间表示,当你想要这样做时,你总会在两端都有反射(匿名和打字对象).所以我想为了优化这一点,你只需要找到最有效的中间形式:http://www.servicestack.net/benchmarks/ (2认同)

Ten*_*giz 13

您的问题归结为一个问题:我可以将一个静态类型变量转换为另一个静态类型变量(来自不同的继承链)吗?而答案显然是否定的.

为什么你的问题归结为上述问题?

  • 动态类型用法编译为使用带反射的Object类型.
  • 您的代码实际上接收Object,(实际上)包含来自一个特定静态类型的值.

因此,实际上,您的代码正在处理分配给Object的静态类型值,并在编译时被视为Dynamic.因此,唯一可以将一个静态类型值转换为另一个[无反射]的情况是它们是同一继承链的一部分.否则,您必须明确地使用反射(由您编写)或隐式使用(由MS编写,具有动态用法).

换句话说,仅当分配给动态的值是Person的基础或派生类型(为示例发明)时,以下代码才有效:

dynamic dPerson = GetDynamicPerson();
Person thePerson = (Person)dPerson;
Run Code Online (Sandbox Code Playgroud)

这就是它.

公平地说,你可以用不安全的代码访问内存地址(比如在C++中)逐字节复制值,但对我而言,这并不比反射更好.

  • 但是冒险远比反射:-) (2认同)

jhe*_*rax 6

在这里,我们可以将匿名对象转换为Dictionary

Dictionary<string, object> dict = 
    obj.GetType()
      .GetProperties()
      .ToDictionary(p => p.Name,  p => p.GetValue(obj, null));
Run Code Online (Sandbox Code Playgroud)

您也可以使用LINQ投射对象:

List<MyType> items = anonymousType.Select(t => new MyType(t.Some, t.Other)).ToList();
Run Code Online (Sandbox Code Playgroud)