Действительно ли это - дыра в динамическом связывании в C# 4?

Я видел очень интересное сообщение на блоге Fabio Maulo. Вот код и ошибка, если Вы не хотите переходить к URL. Я определил новый универсальный класс как так:

public class TableStorageInitializer where TTableEntity : class, new()
    {
        public void Initialize()
        {
            InitializeInstance(new TTableEntity());
        }

        public void InitializeInstance(dynamic entity)
        {
            entity.PartitionKey = Guid.NewGuid().ToString();
            entity.RowKey = Guid.NewGuid().ToString();
        }

    }

Обратите внимание, что InitializeInstance принимает один параметр, который имеет динамичный тип. Теперь для тестирования этого класса я определил другой класс, который вкладывается в моем основном классе Программы как так:

class Program
        {
            static void Main(string[] args)
            {
               TableStorageInitializer x = new TableStorageInitializer();
                x.Initialize();
            }
            private class MyClass
            {
                public string PartitionKey { get; set; }
                public string RowKey { get; set; }
                public DateTime Timestamp { get; set; }
            }
        }

Примечание: внутренний класс "MyClass" объявляется частный.
Теперь, если я выполняю этот код, я получаю Microsoft. До-диез. RuntimeBinder. RuntimeBinderException на строке "объект. PartitionKey = Руководство. NewGuid ().ToString ()".
Интересная часть, хотя то, что в сообщении исключения говорится "Объект, не содержит определение для PartitionKey".
сопроводительный текст http://img697.imageshack.us/img697/4188/testdl.png

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

5
задан Galilyou 5 May 2010 в 15:30
поделиться

1 ответ

Связующее пытается разработать доступный класс для обработки объекта как - в данном случае код выполнение этого вызова не «знает» о классе MyClass , поэтому не «знает» и о PartitionKey .

Я не знаю, насколько тщательно это задокументировано в спецификации C # 4 - хотя я знаю, что обсуждал это по электронной почте с Крисом Берроузом, поэтому подробности могут быть где-то в его блоге :) Имейте в виду, что динамическая привязка со временем изменилась, поэтому более свежие сообщения, вероятно, будут более точными в отношении кода RTM.

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

Есть различные «подводные камни», связанные с динамической типизацией. Явная реализация интерфейса имеет аналогичную проблему:

public int Count(IList list)
{
   int count1 = list.Count; // Fine
   dynamic d = list;
   int count2 = d.Count; // Should work, right?
}

Это не удастся, если вы передадите массив - потому что, хотя IList.Count существует, он реализован явно в массивах - так что это примерно так:

string[] array = new string[10];
Console.WriteLine(array.Count); // Won't compile

Связующее пытается рассматривать объект как его конкретный тип, а не как IList , отсюда и сбой ...

5
ответ дан 14 December 2019 в 19:06
поделиться
Другие вопросы по тегам:

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