这是C#4中动态绑定的漏洞吗?

我在Fabio Maulo的博客上看过一篇非常有趣的post。 如果您不想跳转到url,这是代码和错误。 我定义了一个新的generics类,如下所示:

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接受一个参数,该参数的类型为dynamic。 现在要测试这个类,我定义了另一个嵌套在我的主程序类中的类,如下所示:

 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”被声明为private。
现在,如果我运行此代码,我会在“entity.PartitionKey = Guide.NewGuid()。ToString()”行中获得Microsoft.CSharp.RuntimeBinder.RuntimeBinderException 。
有趣的是,exception的消息是“对象不包含PartitionKey的定义”。
alt text http://img697.imageshack.us/img697/4188/testdl.png

另请注意,如果将嵌套类的修饰符更改为public,则代码将执行而不会出现任何问题。 那么你们认为真正发生在引擎盖下的是什么? 如果您在任何地方都有记录,请参考任何文档 – 当然,您可以找到它们?

绑定器试图找出一个可访问的类来处理对象 – 在这种情况下,调用该代码的代码并不“知道” MyClass类,所以它也不“知道” PartitionKey

我不知道C#4规范中有多详细记录 – 我知道我和Chris Burrows有过关于它的电子邮件对话,所以细节可能在他博客上的某个地方:)请记住动态绑定随着时间的推移已经发生了变化,因此相对于RTM代码,更新的post可能更准确。

认为 ,如果你将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 ,因此失败……