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

Возвращать/потреблять динамический анонимный тип по границам сборки

Код ниже отлично работает. Если методы Get и Use находятся в разных сборках, код не работает с RuntimeBinderException. Это связано с тем, что система времени исполнения .Net гарантирует только общность анонимных типов (<string, int> в этом случае) в рамках сборок.

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

class Program
{
    static void Main(string[] args)
    {
        UsePerson();
        Console.ReadLine();
    }

    public static void UsePerson()
    {
        var person = GetPerson();

        Console.WriteLine(person.Name);
    }

    public static dynamic GetPerson()
    {
        return new { Name = "Foo", Age = 30 };
    }
}
4b9b3361

Ответ 1

Используйте ExpandoObject вместо анонимного типа. Это должно позволить вам безопасно пересекать границы раздела:

public static dynamic GetPerson()
{
    dynamic person = new ExpandoObject();
    person.Name = "Foo";
    person.Age = 30;

    return person;
}

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

Ответ 2

Причиной проблемы является то, что анонимные типы являются внутренними для сборок. Именно поэтому динамический язык Runtime не позволяет вам получать доступ к свойствам из другой сборки.

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

Другое решение возвращает объект открытого класса (с общедоступными свойствами). Это, конечно же, убьет преимущества анонимного типа.

Третье решение будет использовать ExpandoObject, как было предложено Reed Copsey.

Если вы все еще хотите использовать анонимный тип, вы можете написать динамический класс, который "украшает" любой анонимный тип и предоставляет его членам. Такой класс должен был бы реализовать интерфейс IDynamicMetaObjectProvider и получить доступ к украшенному объекту посредством отражения. Возможно, этот материал уже был реализован кем-то там.

Ответ 4

Здесь обходной путь бедного человека; Newtonsoft.Json на помощь, так как сериализация roundtrip генерирует экземпляры динамического типа, видимые вашей/рабочей сборке.

public static class TypeExt
{
  // roundtrip json serialization to enable access to dynamic members and properties originating from another assembly
  public static T JClone<T>( this T source ) { return JsonConvert.DeserializeObject<T>( JsonConvert.SerializeObject( source ) ); }
}

Ответ 5

экспромтом-интерфейс

http://code.google.com/p/impromptu-interface/

Позволяет использовать экземпляр анонимного типа через границы, но вы должны объявить интерфейс, который соответствует его подписи или по крайней мере того, что вы хотите получить от него.