2011-05-12 51 views
23

我有一个情况,其中两班(从另一个推导)都实现明确的相同的接口:如何调用基类的显式实现接口方法

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

从派生类执行I.M(),我想调用基类的实现,但我不知道该怎么做。我试过到目前为止,这是(B类):

int I.M() { 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 I.M() { return ((this as A) as I).M() + 2; } 
// this results in an endless loop, since it calls B's implementation 

有没有办法做到这一点,而无需执行其他(非界面显式)辅助方法?


更新

我知道这是可能的一个“助手”方法,可以通过派生类中调用,如:

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

我也可以改变它来实现界面非明确。但我只是想知道是否有可能没有任何这些解决方法。

回答

17

不幸的是,这是不可能的。
甚至没有辅助方法。辅助方法有同样的问题,你的第二次尝试:thisB型的,即使是在基类,并调用M的实施B

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

唯一的解决办法是在A一个辅助方法即在A的实施M使用:

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

但是,你将需要提供一种方法,这样也为B是否会有一个class C : B, I ...

+0

是的,解决方法是我已经添加到更新的问题。但这不是我想知道的。 – M4N 2011-05-12 10:06:01

+1

@ M4N:这只是为了让答案更大一些;-)真正的答案是第一句话:没有这种解决方法,这是不可能的。 – 2011-05-12 10:07:50

+4

要添加到为什么它是不可能的:明确实现的接口方法是私有的 - 使他们无法从派生类调用。您应该更喜欢不同的方法,比如Daniel列出的方法,以避免*调用super *代码味道。 – 2011-05-12 10:18:57

0

它需要明确吗?...您可以使用抽象类或类而不是接口吗?

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

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

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

+0

不! B具有不同于A的接口实现(它增加了A的实现)。 – M4N 2011-05-12 09:56:10

+0

@ M4N - 然后你只能扩展A覆盖该方法并对该方法进行基础调用并继续实现该方法。 – Amedio 2011-05-12 10:00:30

+0

查看更新的问题。 (显式实现不是必需的,但我只是想知道是否有可能) – M4N 2011-05-12 10:03:48

10

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

interface I 
{ 
    int M(); 
} 

class A : I 
{ 
    int I.M() { return 1; } 
} 

class B : A, I 
{ 
    BaseClassExplicitInterfaceInvoker<B> invoker = new BaseClassExplicitInterfaceInvoker<B>(); 
    int I.M() { return invoker.Invoke<int>(this, "M") + 2; } 
} 

public class BaseClassExplicitInterfaceInvoker<T> 
{ 
    private Dictionary<string, MethodInfo> cache = new Dictionary<string, MethodInfo>(); 
    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<RT>(T obj, string methodName) 
    {    
     MethodInfo method = FindMethod(methodName); 
     return (RT)method.Invoke(obj, null); 
    } 

} //public static class BaseClassExplicitInterfaceInvoker<T> 

Here是我的灵感来源。

+0

工程就像一个魅力。在这种情况下,反思就是要走的路。 – 2013-02-01 12:02:48

+2

仅仅因为你可以做某件事情并不意味着你必须这样做。 – Unknown 2013-03-25 12:34:53

+1

仅仅因为你应该考虑不做某事并不意味着没有这样做的实例是不可或缺的;-) @Roland,感谢分享,是一种享受! – Dav 2014-05-21 22:58:06

0

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

我有两个界面 - >接口1和接口2

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 
} 
0
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(); 
     } 
    } 
} 
+1

添加一些探索 – HaveNoDisplayName 2016-09-04 04:07:37

0

这是我的Roland Pihlakas的解决方案。该版本支持整个继承链而不是直接的基类。 Invoke方法包含其他参数,并且有一个用于非函数方法的void类型Invoke。

public class BaseClassExplicitInterfaceInvoker<T> 
{ 
    readonly Dictionary<string, MethodInfo> Cache = new Dictionary<string, MethodInfo>(); 

    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<ReturnType>(T Object, string MethodName, params object[] Parameters) => (ReturnType)FindMethod(MethodName).Invoke(Object, Parameters); 
} 
相关问题