`
RednaxelaFX
  • 浏览: 3047685 次
  • 性别: 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信息。
分享到:
评论

相关推荐

    细细品味C#(抽象接口委托反射)

    实现接口的类需要提供接口中所有成员的具体实现。例如: ```csharp public class MyClass : IMyInterface { public void MyMethod() { // 实现细节 } public int GetValue() { return 10; // 示例返回值 }...

    21-04-03_FactoryPattern(001_在工厂模式下以通过接口结合列表、泛型和反射等方式实现指定类型的实例化操作_控制台).rar

    在这个“21-04-03_FactoryPattern(001_在工厂模式下以通过接口结合列表、泛型和反射等方式实现指定类型的实例化操作_控制台)”案例中,我们将探讨如何利用接口、泛型和反射等技术来进一步增强工厂模式的功能。...

    java接口的不同使用

    - 类通过关键字`implements`来实现接口,并且必须提供接口中所有抽象方法的实现。 - 如果类不提供接口中某个抽象方法的实现,那么该类必须声明为抽象类(abstract class)。 - 实现接口时,可以重写接口中默认...

    细细品味C#(抽象接口委托反射)(转自博客园)

    接口也不能直接实例化,但所有成员都必须由实现类显式实现。 2. **继承性:** 抽象类支持单一继承,即一个类只能继承一个抽象类;接口支持多重继承,即一个类可以实现多个接口。 3. **成员实现:** 抽象类可以包含已...

    Go-grpcall是一个客户端库利用反射模式轻松请求GRPC服务器

    使用Go-grpcall,开发者不再需要显式地实例化存根,只需提供服务名和方法名,即可动态生成并执行请求。 Go-grpcall的一个重要应用场景是制作grpc代理模式中间件,例如grpc-gateway。grpc-gateway是一个反向代理,它...

    动态调用WebService加反射缓存可反射类型

    在Java和.NET等面向对象的语言中,反射是强大的工具,可以用于实现元编程,即在程序运行时动态地创建对象、调用方法、访问字段等。 在动态调用WebService时,反射可以用来获取WebService的接口信息,动态地创建服务...

    Java中的反射实现数据库操作

    在Java编程语言中,反射是一种强大的机制,它允许我们在运行时检查类、接口、字段和方法的信息,并且能够在不知道对象具体类型的情况下调用其方法或访问其属性。反射是Java提供的一种动态类型功能,这对于创建灵活、...

    PHP基于反射机制实现自动依赖注入的方法详解

    反射是PHP的一个强大特性,它允许程序在运行时检查类、接口、方法和属性的信息。在依赖注入的上下文中,反射机制被用来动态地获取类的构造函数或方法的参数信息,以便于创建和注入相应的依赖对象。 首先,我们看一...

    java反射与泛型综合例子

    泛型是Java SE 5.0引入的新特性,它允许在定义类、接口和方法时使用类型参数,从而提高代码的类型安全性和可读性。泛型的主要优点是可以避免强制类型转换,并在编译时检查类型安全。例如,你可以定义一个泛型类`...

    c#显示接口和隐式接口

    在C#编程中,接口(Interface)是一种定义行为规范的类型,它允许类或结构体遵循特定的约定,实现接口中的所有成员。接口可以包含方法、属性、索引器和事件,但不能包含字段或构造函数。接口有两种实现方式:隐式...

    用反射实现向不同简单JavaBean填充值的实现代码

    在Java编程中,反射是一种强大的工具,它允许我们在运行时检查和操作类、接口、字段以及方法的信息。这里我们关注的是如何使用反射来向简单的JavaBean对象中设置和获取值,而不必显式地创建这些对象。这个过程涉及到...

    Java_Spring反射

    6. **数据绑定**:Spring MVC中,表单数据与控制器方法参数之间的绑定也是通过反射完成的。它可以自动将请求参数映射到方法参数上,简化了处理HTTP请求的工作。 7. **事件驱动**:Spring应用上下文支持事件发布和...

    Android:如何显式调用蓝牙的配对功能

    总之,通过Java的反射机制,我们可以访问并调用Android系统中的隐藏API,实现蓝牙设备的显式配对和解配对。然而,这种方法并不稳定,可能会因为Android版本更新或安全策略改变而失效。因此,建议开发者关注官方SDK的...

    C#泛型、反射实例、自动生成sql语句

    在C#中,我们可以定义泛型类、泛型接口、泛型方法等。例如,`List&lt;T&gt;`就是一个常见的泛型类,其中`T`代表一个未知的数据类型,可以是任何引用类型或值类型。使用泛型可以避免装箱和拆箱操作,提升性能,并确保类型...

    C++反射机制

    在反射中,虚函数可以用于实现动态的方法调用。 5. **静态成员和枚举**:静态成员可以用来存储类的元数据,例如方法名和参数类型。枚举可以用来表示特定的反射操作,如创建实例、调用方法等。 6. **映射表...

    设计模式1

    3.继承这个接口的类必须实现接口的所有方法,且必须为public实现:当一个类实现接口时,它必须提供接口中所有方法的具体实现。这些实现的方法必须是public的,因为接口中的方法默认就是public的,这符合接口的契约...

    为了高效地将Json对象转化成Java bean对象,传统上我们是在运行是利用反射来实现.zip

    反射允许我们在运行时检查类、接口、字段和方法的信息,并且能够在运行时动态地创建对象和调用方法。以下是一个简化的转换过程: 1. **解析JSON字符串**:首先,我们需要一个JSON字符串。这个字符串可以来源于HTTP...

    JAVA5泛型和反射

    在 Java 中,泛型的声明通常是在类、接口或方法的名称后面跟上一对尖括号 `&lt;T&gt;`,其中 `T` 是类型参数。例如: ```java class GenericClass&lt;T&gt; { T someField; void someMethod(T t) { // ... } } ``` 这里的 ...

Global site tag (gtag.js) - Google Analytics