'Динамичный' C# не может получить доступ к свойствам от анонимных типов, объявленных в другом блоке

Код ниже работает хорошо, пока у меня есть класс ClassSameAssembly в том же блоке как класс Program. Но когда я перемещаю класс ClassSameAssembly к отдельному блоку, a RuntimeBinderException (см. ниже), брошен. Действительно ли возможно разрешить его?

using System;

namespace ConsoleApplication2
{
    public static class ClassSameAssembly
    {
        public static dynamic GetValues()
        {
            return new
            {
                Name = "Michael", Age = 20
            };
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            var d = ClassSameAssembly.GetValues();
            Console.WriteLine("{0} is {1} years old", d.Name, d.Age);
        }
    }
}

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'объект' не содержит определение для 'Имени'

at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at ConsoleApplication2.Program.Main(String[] args) in C:\temp\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
85
задан CodeFox 22 January 2016 в 08:46
поделиться

2 ответа

Я полагаю, что проблема в том, что анонимный тип генерируется как внутренний, поэтому связующее устройство на самом деле не "знает" о нем как о таковом.

Попробуйте вместо этого использовать ExpandoObject:

public static dynamic GetValues()
{
    dynamic expando = new ExpandoObject();
    expando.Name = "Michael";
    expando.Age = 20;
    return expando;
}

Я знаю, что это несколько уродливо, но это лучшее, что я могу придумать на данный момент... Я не думаю, что вы можете даже использовать инициализатор объекта с ним, потому что, хотя он сильно типизирован как ExpandoObject, компилятор не будет знать, что делать с "Name" и "Age". Вы можете сделать вот так:

 dynamic expando = new ExpandoObject()
 {
     { "Name", "Michael" },
     { "Age", 20 }
 };
 return expando;

но это не намного лучше...

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

return new { Name = "Michael", Age = 20 }.ToExpando();

Это довольно ужасно :(

113
ответ дан 24 November 2019 в 08:15
поделиться

Вы можете использовать [assembly: InternalsVisibleTo("YourAssemblyName")], чтобы сделать внутренние компоненты вашей сборки видимыми.

61
ответ дан 24 November 2019 в 08:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: