Возврат / использование динамического анонимного типа через границы сборки - PullRequest
25 голосов
/ 08 июня 2010

Код ниже прекрасно работает.Если методы 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 };
    }
}

Ответы [ 5 ]

34 голосов
/ 08 июня 2010

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

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

    return person;
}

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

8 голосов
/ 08 июня 2010

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

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

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

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

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

1 голос
/ 16 июня 2016

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

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 ) ); }
}
1 голос
/ 08 июля 2010

Другим хорошим решением может быть использование кортежей, представленных в .Net 4: http://msdn.microsoft.com/en-us/library/dd268536.aspx

0 голосов
/ 02 марта 2011

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

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

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

...