`
RednaxelaFX
  • 浏览: 3015413 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

反射与显式实现接口的方法

    博客分类:
  • C#
阅读更多
前一帖里,我用到了下面三处Expression.Call()的调用。它们都需要一个MethodInfo参数来指定调用的方法,我就通过直观的反射来得到这些参数。
// 1
Expression.Call(
    Expression.Constant(list),
    typeof(IEnumerable<int>).GetMethod("GetEnumerator"))

// 2
Expression.Call(
    vIter,
    typeof(IEnumerator).GetMethod("MoveNext"))

// 3
Expression.Call(
    typeof(Console).GetMethod("WriteLine", new[] { typeof(int) }),
    new[] { vI })

其中,在注释1的地方我要实现的是list.GetEnumerator()的效果,list是一个IOrderedEnumerable<int>类型的变量;
在注释2的地方我要实现的是iter.MoveNext(),iter是一个IEnumerator<int>类型的变量,由ParameterExpression类型的vIter提供。

要是把这两处代码改一下,变成这样:
// 1
Expression.Call(
    Expression.Constant(list),
    list.GetType().GetMethod("GetEnumerator"))

// 2
Expression.Call(
    vIter,
    vIter.Type.GetMethod("MoveNext"))

也就是获取变量的类型然后对其做反射来查找方法,就会……在运行时得到NullReferenceException。为什么?

仔细观察可以留意到,IOrderedEnumerable<T>中GetEnumerator()方法是显式实现IEnumerable<T>的;IEnumerator<T>的MoveNext()是显式实现IEnumerator的。
在C#中,如果显式实现一个接口,那么显式实现的方法就会被标记为私有的。Type.GetMethod()方法默认只寻找公有成员,于是就出错了。
C#语言规范里有这么一段:
C# Language Specification 写道
Explicit interface member implementations have different accessibility characteristics than other members. Because explicit interface member implementations are never accessible through their fully qualified name in a method invocation or a property access, they are in a sense private. However, since they can be accessed through an interface instance, they are in a sense also public.

总之要用反射找这样的显式实现接口的方法,在GetMethod()的时候记得带上BindingFlags.NonPublic没错的~

P.S. CLI里并没有“显式实现接口”的概念,只有mapped和implicit实现的区别。这里提到的显式实现接口是C#语言的规则而已。

P.P.S Chris Brumme以前写过一帖详细描述了显式实现接口生成的代码,Interface Layout。CLR要理解C#的显式接口实现,关键在于显式实现接口方法的方法体里的.override信息。
分享到:
评论

相关推荐

    插件式GIS应用框架的设计与实现

    2.2.2 实现接口与显式实现接口 2.2.3 C#的实现继承 2.2.4 继承和重用 2.3 框架宿主程序设计与实现 2.3.1 属性——合理冲破私有变量访问限制 2.3.2 动手——从宿主程序开始 2.4 框架通信契约设计 2.4.1 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    11.4 显式实现事件 第12章 泛型 12.1 Framework类库中的泛型 12.2 Wintellect的Power Collections库 12.3 泛型基础结构 12.3.1 开放和封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码...

    C#本质论(第3版)

    4.1.7 语句与方法调用的比较 4.2 方法的声明 4.2.1 参数声明 4.2.2 方法返回值声明 4.3 uslng指令 4.4 main()的返回值和参数 4.5 参数 4.5.1 值参数 4.5.2 引用参数 4.5.3 输出参数 4.5.4 参数数组 ...

    c#显示接口和隐式接口

    显式接口实现(C# 编程指南)  并且这两个接口包含具有相同签名的成员, 那么在类中实现该成员将 如果类实现两个接口, 导致两个接口都使用该成员作为它们的实现。  例如: interface IControl ...

    Programming C#(第4版)(中文版)part1

    实现接口 145 访问接口方法 154 重定义接口的实现 162 显式接口实现 166 第9章 数组、索引器与集合 176 数组 176 foreach语句 181 索引器 197 集合接口 206 约束 210 List&lt;T&gt; 215 队列 226 栈 229 字典 232 第10章 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part1

    11.4 显式实现事件 第12章 泛型 12.1 Framework类库中的泛型 12.2 Wintellect的Power Collections库 12.3 泛型基础结构 12.3.1 开放和封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码...

    CLR.via.C#.(中文第3版)(自制详细书签)

    11.4 显式实现事件 第12章 泛型 12.1 Framework类库中的泛型 12.2 Wintellect的Power Collections库 12.3 泛型基础结构 12.3.1 开放和封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码...

    Programming C#(第4版)(中文版)part3

    实现接口 145 访问接口方法 154 重定义接口的实现 162 显式接口实现 166 第9章 数组、索引器与集合 176 数组 176 foreach语句 181 索引器 197 集合接口 206 约束 210 List&lt;T&gt; 215 队列 226 栈 229 字典 232 第10章 ...

    Programming C#(第4版)(中文版)part2

    实现接口 145 访问接口方法 154 重定义接口的实现 162 显式接口实现 166 第9章 数组、索引器与集合 176 数组 176 foreach语句 181 索引器 197 集合接口 206 约束 210 List&lt;T&gt; 215 队列 226 栈 229 字典 232 第10章 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part3

    11.4 显式实现事件 第12章 泛型 12.1 Framework类库中的泛型 12.2 Wintellect的Power Collections库 12.3 泛型基础结构 12.3.1 开放和封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码...

    uncapsulator:通过动态代理进行.NET反射的Fluent API

    在这种情况下,普通动态绑定是不可靠的,因为它在使用显式实现的接口成员时会失败。 Uncapsulator类似于类固醇上的 ,它基于Joseph Albahari编写的的内置功能。 入门 可以通过同名的NuGet软件包下载解封装器。 ...

    JAVA面试题最全集

    写一个方法,实现字符串的反转,如:输入abc,输出cba 写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出bbbhhtccc。 3.数据类型之间的转换 如何将数值型字符转换为数字(Integer,Double) 如何将数字...

    轻松学C#(图解版)

    10.6 显式实现接口 190 10.7 小结 194 10.8 习题 194 第三篇 应用技术篇 第11章 异常处理 200 11.1 异常处理的基础 200 11.1.1 什么是异常 200 11.1.2 未捕获异常的后果 200 11.1.3 常用异常 201 11.1.4 异常处理 ...

    net学习笔记及其他代码应用

    接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它...

    C#5.0本质论第四版(因文件较大传的是百度网盘地址)

    4.1.7 语句与方法调用的比较 108 4.2 方法的声明 108 4.2.1 形式参数声明 109 4.2.2 方法返回类型声明 110 4.3 using指令 111 4.4 Main()的返回值和参数 114 4.5 方法的参数 116 4.5.1 ...

Global site tag (gtag.js) - Google Analytics