如何在基类上调用显式实现的接口方法

我有一种情况,其中两个类(一个派生自另一个)都明确地实现相同的接口:

interface I { int M(); } class A : I { int IM() { return 1; } } class B : A, I { int IM() { return 2; } } 

从派生类的IM() ,我想调用基类的实现,但我不知道如何做到这一点。 到目前为止我尝试过的是(在B级):

 int IM() { return (base as I).M() + 2; } // this gives a compile-time error //error CS0175: Use of keyword 'base' is not valid in this context int IM() { return ((this as A) as I).M() + 2; } // this results in an endless loop, since it calls B's implementation 

有没有办法做到这一点,而不必实现另一个(非接口显式)辅助方法?


更新

我知道可以使用派生类调用的“帮助器”方法,例如:

 class A : I { int IM() { return M2(); } protected int M2 { return 1; } } 

我也可以更改它以非显式地实现接口。 但我只是想知道是否有可能没有任何这些变通方法。

不幸的是,这是不可能的。
甚至没有辅助方法。 辅助方法与第二次尝试具有相同的问题: this是类型B ,即使在基类中也会调用BM实现:

 interface I { int M(); } class A : I { int IM() { return 1; } protected int CallM() { return (this as I).M(); } } class B : A, I { int IM() { return CallM(); } } 

唯一的解决方法是A中的辅助方法,用于AM实现:

 interface I { int M(); } class A : I { int IM() { return CallM(); } protected int CallM() { return 1; } } class B : A, I { int IM() { return CallM(); } } 

但是你需要为B提供这样的方法,如果有一个class C : B, I ……

可以使用reflection。
代码如下。 我将缓存添加为基本优化,但可以通过在methodInfo上使用Delegate.CreateDelegate进一步优化methodInfo 。 此外,可以使用methodInfo.GetParameters()添加参数计数和类型检查。

 interface I { int M(); } class A : I { int IM() { return 1; } } class B : A, I { BaseClassExplicitInterfaceInvoker invoker = new BaseClassExplicitInterfaceInvoker(); int IM() { return invoker.Invoke(this, "M") + 2; } } public class BaseClassExplicitInterfaceInvoker { private Dictionary cache = new Dictionary(); private Type baseType = typeof(T).BaseType; private MethodInfo FindMethod(string methodName) { MethodInfo method = null; if (!cache.TryGetValue(methodName, out method)) { var methods = baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (var methodInfo in methods) { if (methodInfo.IsFinal && methodInfo.IsPrivate) //explicit interface implementation { if (methodInfo.Name == methodName || methodInfo.Name.EndsWith("." + methodName)) { method = methodInfo; break; } } } cache.Add(methodName, method); } return method; } public RT Invoke(T obj, string methodName) { MethodInfo method = FindMethod(methodName); return (RT)method.Invoke(obj, null); } } //public static class BaseClassExplicitInterfaceInvoker 

这是我灵感的源泉。

有必要明确吗?…你可以使用抽象类或类而不是接口吗?

 interface ISample {} class A : ISample {} class B : A {} ... base.fun(); ... 

http://msdn.microsoft.com/en-us/library/hfw7t1ce(v=vs.71).aspx

当它来自接口的实现时,我不知道它不可能的调用基方法。

你不能在基类中调用Explicit接口方法,这里我解决了这个问题

我有两个接口 – > Interface1和Interface2

 public interface Interface1 { string method2(); } public interface Interface2 { string method22(); } 

主类方法

 class Program { static void Main(string[] args) { class1 cls = new class1(); string str = cls.method2(); } } 

和我的界面实现了类

 class class1 : Interface1, Interface2 { #region Interface1 Members public string method2() { return (this as Interface2).method22(); } #endregion #region Interface2 Members string Interface2.method22() { return "2"; } #endregion } 
 using System; namespace SampleTest { interface IInterface1 { void Run(); } interface IInterface2 { void Run(); } public class BaseClass : IInterface1, IInterface2 { public void Interface1Run() { (this as IInterface1).Run(); } public void Interface2Run() { (this as IInterface2).Run(); } void IInterface2.Run() { Console.WriteLine("I am from interface 2"); } void IInterface1.Run() { Console.WriteLine("I am from interface 1"); } } public class ChildClass : BaseClass { public void ChildClassMethod() { Interface1Run(); Interface2Run(); } } public class Program : ChildClass { static void Main(string[] args) { ChildClass childclass = new ChildClass(); childclass.ChildClassMethod(); } } } 

这是我的Roland Pihlakas版本的不错解决方案。 此版本支持整个inheritance链而不是直接基类。 Invoke方法包含其他参数,并且对于非函数方法存在void类型Invoke。

 public class BaseClassExplicitInterfaceInvoker { readonly Dictionary Cache = new Dictionary(); MethodInfo FindMethod(string MethodName) { if (Cache.TryGetValue(MethodName, out var Result)) return Result; var BaseType = typeof(T); while (Result == null) { if ((BaseType = BaseType.BaseType) == typeof(object)) break; var Methods = BaseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); Result = Methods.FirstOrDefault(X => X.IsFinal && X.IsPrivate && (X.Name == MethodName || X.Name.EndsWith("." + MethodName))); } if (Result != null) Cache.Add(MethodName, Result); return Result; } public void Invoke(T Object, string MethodName, params object[] Parameters) => FindMethod(MethodName).Invoke(Object, Parameters); public ReturnType Invoke(T Object, string MethodName, params object[] Parameters) => (ReturnType)FindMethod(MethodName).Invoke(Object, Parameters); }