这是C#4中动态绑定的一个漏洞吗? [英] Is this a hole in dynamic binding in C# 4?

查看:52
本文介绍了这是C#4中动态绑定的一个漏洞吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Fabio Maulo的文章中看到了一个非常有趣的文章博客。如果您不想跳转到网址,则此处是代码和错误。我定义了一个新的通用类,如下所示:

 公共类TableStorageInitializer< TTableEntity>其中TTableEntity:class,new()
{
public void Initialize()
{
InitializeInstance(new TTableEntity());
}

public void InitializeInstance(动态实体)
{
entity.PartitionKey = Guid.NewGuid()。ToString();
entity.RowKey = Guid.NewGuid()。ToString();
}

}

请注意,InitializeInstance接受一个参数,这是动态类型。现在要测试该类,我定义了另一个嵌套在主Program类中的类,如下所示:

 类程序
{
static void Main(string [] args)
{
TableStorageInitializer< MyClass> x =新的TableStorageInitializer< MyClass>();
x.Initialize();
}
私有类MyClass
{
public string PartitionKey {get;组; }
公共字符串RowKey {get;组; }
public DateTime Timestamp {get;组; }
}
}

注意:内部类 MyClass被声明私人的。

现在,如果我运行此代码,我将得到
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

有趣的部分是,异常消息显示对象不包含PartitionKey的定义。

替代文字http://img697.imageshack.us/img697/4188/testdl.png



还请注意,如果您将嵌套类的修饰符更改为public,则代码将毫无问题地执行。那么你们认为到底发生了什么呢?请参阅任何文档-当然,如果您在任何地方都可以找到文档,您可能会发现?

解决方案

活页夹试图计算出 accessible 类以将对象视为-在这种情况下,进行该调用的代码不会了解 MyClass 类,因此它不会了解 PartitionKey

我不知道C#4规范对此进行了详尽的记录-我知道我已经与Chris Burrows进行了电子邮件对话但是,因此详细信息可能在他的博客上的某处:)请记住,动态绑定具有随时间变化,因此有关RTM代码的最新帖子可能更准确。



认为如果您将 PartitionKey 到私有类实现的公共接口中,该可以起作用-但您必须尝试一下。



动态类型周围存在各种陷阱。显式接口实现有一个类似的问题:

  public int Count(IList list)
{
int count1 = list.Count; //罚款
动态d =列表;
int count2 = d.Count; //应该可以,对吧?
}

如果您传入数组,则会失败-因为尽管 IList.Count 存在,它是在数组中显式实现的-有点像这样:

  string [] array = new string [10]; 
Console.WriteLine(array.Count); //不会编译

活页夹试图将对象视为其具体类型,而不是 IList ,因此失败了。


I've seen a very interesting post on Fabio Maulo's blog. Here's the code and the bug if you don't want to jump to the url. I defined a new generic class like so:

public class TableStorageInitializer<TTableEntity> 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();
        }

    }

Note that InitializeInstance accepts one parameter, which is of type dynamic. Now to test this class, I defined another class that is nested inside my main Program class like so:

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

Note: the inner class "MyClass" is declared private.
Now if i run this code I get a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException on the line "entity.PartitionKey = Guide.NewGuid().ToString()".
The interesting part, though is that the message of the exception says "Object doesn't contain a definition for PartitionKey".
alt text http://img697.imageshack.us/img697/4188/testdl.png

Also note that if you changed the modifier of the nested class to public, the code will execute with no problems. So what do you guys think is really happening under the hood? Please refer to any documentation -of course if this is documented anywhere- that you may find?

解决方案

The binder tries to work out an accessible class to treat the object as - in this case, the code making that call doesn't "know" about the MyClass class, so it doesn't "know" about PartitionKey either.

I don't know how thoroughly this is documented in the C# 4 spec - I know I've had an email conversation about it with Chris Burrows though, so the details may be somewhere on his blog :) Bear in mind that the dynamic binding has changed over time, so more recent posts are likely to be more accurate with respect to the RTM code.

I think that if you put PartitionKey into a public interface that the private class implements, that may work - but you'd have to try it.

There are various "gotchas" around dynamic typing. Explicit interface implementation has a similar problem:

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

This will fail if you pass in an array - because although IList.Count exists, it's implemented explicitly in arrays - so it's a bit like this:

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

The binder tries to treat the object as its concrete type, not as IList, hence the failure...

这篇关于这是C#4中动态绑定的一个漏洞吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆