Код ниже работает отлично. Если 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 };
}
}
Используйте ExpandoObject вместо анонимного типа. Это должно позволить вам безопасно пересекать границы сборки:
public static dynamic GetPerson()
{
dynamic person = new ExpandoObject();
person.Name = "Foo";
person.Age = 30;
return person;
}
В общем, анонимные типы действительно должны использоваться только в том же методе, в котором они созданы. Возврат анонимного типа из метода, как правило, вызывает больше проблем, чем решает.
Причина проблемы в том, что анонимные типы являются внутренними для сборок. Вот почему среда выполнения динамического языка не позволяет вам получать доступ к свойствам из другой сборки.
Одно решение объясняется в этом сообщении . Вы можете поместить в сборку настраиваемый атрибут, определяющий анонимный тип, позволяющий другой сборке получить доступ к своим внутренним компонентам.
Другое решение - возврат объекта открытого класса (с общедоступными свойствами). Это, конечно, убьет преимущества анонимного типа.
Третье решение - использовать ExpandoObject , как было предложено Ридом Копси .
Если вы все еще хотите использовать анонимный тип, вы можете написать динамический класс, который «украшает» любой анонимный тип и предоставляет его члены. Такой класс должен реализовать интерфейс IDynamicMetaObjectProvider и обращаться к декорированному объекту через отражение. Возможно, это уже кто-то реализовал.
Другим хорошим решением может быть использование кортежей, которые были введены в .Net 4: http://msdn.microsoft.com/en-us/library/dd268536.aspx