Я видел очень интересное сообщение на блоге 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
Также обратите внимание, что при изменении модификатора вложенного класса общественности код выполнится без проблем. Таким образом, то, что делает Вас, парни думают, действительно происходит под капотом? См. какую-либо документацию - конечно, если это документируется где-нибудь - что можно найти?
Связующее пытается разработать доступный класс для обработки объекта как - в данном случае код выполнение этого вызова не «знает» о классе 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
, отсюда и сбой ...