Подтвердить что ты не робот

Есть ли способ конвертировать динамический или анонимный объект в строго типизированный объявленный объект?

Если у меня есть динамический объект или анонимный объект, структура которого точно соответствует структуре строго типизированного объекта, существует ли способ .NET для создания типизированного объекта из динамического объекта?

Я знаю, что могу использовать тип LINQ dynamicList.Select(dynamic => new Typed { .... }, или я могу использовать Automapper, но мне интересно, нет ли чего-то специально для этого?

4b9b3361

Ответ 1

Вы можете сериализовать в промежуточный формат, просто чтобы десериализовать его сразу после этого. Это не самый элегантный или эффективный способ, но он может выполнить вашу работу:

Предположим, это ваш класс:

// 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), если круговая передача симметрична.

Ответ 2

Ваш вопрос сводится к вопросу: могу ли я преобразовать одну типизированную переменную статически в другую типизированную переменную статически (из разных цепочек наследования)? и ответ, очевидно, Нет.

Почему ваш вопрос сводится к указанному выше вопросу?

  • Использование динамического типа компилируется с использованием типа Object с отражением.
  • Ваш код получает Object в действительности, который (в действительности) содержит значение от одного конкретного статического типа.

Таким образом, на самом деле ваш код имеет дело со статически типизированным значением, назначенным объекту, и обрабатывается как Dynamic во время компиляции. Поэтому единственный случай, когда вы можете преобразовать одно статически типизированное значение в другое [без отражения], - это когда они являются частью одной и той же цепи наследования. В противном случае вы обязательно будете использовать отражение явно (написанное вами) или неявно (написанное MS с использованием Dynamic).

Другими словами, следующий код будет работать, только если значение, назначенное динамическому, является базовым или производным типом Person (изобретенным для примера):

dynamic dPerson = GetDynamicPerson();
Person thePerson = (Person)dPerson;

Это в значительной степени.

Справедливо отметить, что вы можете копировать байты по байтам с небезопасным кодом, обращающимся к адресам памяти (например, на С++), но для меня это не лучше, чем отражение.

Ответ 3

Здесь мы можем преобразовать анонимный объект в словарь

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

Ответ 4

Если ваш объект наследуется от MarshalByRefObject, вы можете использовать RealProxy.

Другой альтернативой является использование Reflection, но вы можете быть ограничены материалами, не отмеченными виртуальными и/или использующими интерфейсы. Вы также можете скопировать значения, предполагая, что свойства доступны для записи, и пустой конструктор работает для вашего случая.

Фактический ответ на ваш вопрос - нет, нет автоматического способа обработки динамического объекта как определенного типа, если он не является экземпляром этого типа, и нет никакого автоматического средства для копирования значений из динамического/анонимного объект в экземпляр именованного класса.

Время выполнения не имеет представления о том, что происходит в конструкторе, или о том, как класс реализован внутри, поэтому любое такое средство выведет из системы безопасность типа. Весь смысл динамического состоит в том, чтобы разрешить отправку/печать времени утки /etc.

edit: Если я неправильно понял вопрос, дайте мне знать, но я предполагаю, что вы хотите рассматривать динамический объект, как если бы это был экземпляр SomeType.

В моих собственных проектах я использовал класс Object Mapper для этого, где он соответствует именам свойств для доступных для записи свойств и одинаковых или принудительных типов, поэтому, по крайней мере, мне не пришлось писать 10 000 строк шаблона, хотя мой источник не был динамическим, поэтому я использовал Reflection.Emit/DynamicMethod, чтобы значительно ускорить его.