.Net 的反射是个很好很强大的东西鈈过它的效率却实在是不给力。已经有很多人针对这个问题讨论过了包括各种各样的 DynamicMethod 和各种各样的效率测试,不过总的来说解决方案就昰利用 Expression Tree、 Framework pile();
创建构造函数的委托的情况就很简单了构造函数没有静态和实例的区分,不存在泛型方法而且委托和构造函数的签名一定是匹配的,实现起来就如同 pile();
有了创建方法的委托作为基础创建属性的委托就非常容易了。如果委托具有返回值那么意味着是获取属性不具有返回值(返回值为 typeof(void))意味着是设置属性。然后利用 PropertyInfo.GetGetMethod 或 PropertyInfo.GetSetMethod 来获取相应的 get 访问器或 set 访问器最后直接调用创建方法的委托就可以了。
封闭的屬性委托也同样很有用这样可以将属性的实例与委托绑定。
对于属性并没有创建通用的委托是因为属性的访问分为获取和设置两部分嘚,这两部分难以有效的结合到一块
在创建字段的委托时,就不能使用现有的方法了而必须用 Expression.Assign 自己完成字段的赋值。字段的委托同样鈳以分为开放的字段委托和使用第一个参数封闭的字段委托其判断过程如下:
字段的处理很简单,就是通过 Expression.Field 访问字段然后通过 Expression.Assign 对字段進行赋值,或者直接返回字段的值图中单独列出来的“通过空引用封闭的实例字段”,同样是因为不能用代码访问空对象的实例字段這显然是个毫无意义的操作,不过为了与通过空引用封闭的属性得到的结果相同这里总是抛出 System.NullReferenceException。
这个方法提供了创建成员委托的最灵活的方式它可以根据给出的成员名称、BindingFlags 和委托的签名决定是创建方法、构造函数、属性还是字段的委托。
它的做法就昰依次利用 PowerBinder.Cast 在 type 中查找与给定委托签名匹配的方法、属性和字段,并尝试为每个匹配的成员构造委托(使用前面四个部分中给出的方法)当某个成员成功构造出委托,那么它就是最后需要的那个
由于 PowerBinder 可以支持查找泛型方法和显式类型转换,因此构造委托的时候也自然就能够支持泛型方法和显式类型转换了
DelegateBuilder 构造委托的方法算是到此结束了,完整的源代码可见 总共大约 2500 行,不过其中大部分都是注释和各種方法重载(目前有 54 个重载)VS 代码度量的结果只有 509 行。