简体   繁体   English

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

[英]How to call an explicitly implemented interface-method on the base class

I have a situation, where two classes (one deriving from the other) both implement the same interface explicitly:我有一种情况,其中两个类(一个派生自另一个)都显式实现了相同的接口:

interface I
{
  int M();
}

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

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

From the derived class' implementation of IM() , I'd like to call the implementation of the base class, but I don't see how to do it.从派生类的IM() ,我想调用基类的实现,但我不知道如何去做。 What I tried so far is this (in class B):到目前为止,我尝试过的是(在 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

Is there a way to do this, without having to implement another (non interface-explicit) helper method?有没有办法做到这一点,而不必实现另一个(非接口显式)辅助方法?


Update :更新

I know it's possible with a "helper" method which can be called by the derived class, eg:我知道可以使用派生类可以调用的“帮助程序”方法,例如:

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

I can also change it to implement the interface non-explicitly.我也可以更改它以非显式地实现接口。 But I was just wondering if it's possible without any of these workarounds.但我只是想知道如果没有任何这些解决方法是否可能。

Unfortunately, it isn't possible.不幸的是,这是不可能的。
Not even with a helper method.甚至没有帮助方法。 The helper method has the same problems as your second attempt: this is of type B , even in the base class and will call the implementation of M in B :辅助方法与您的第二次尝试存在相同的问题: thisB类型,即使在基类中也会调用BM实现:

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

The only workaround would be a helper method in A that is used in A 's implementation of M :唯一的解决方法是A中的辅助方法,用于AM实现:

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

But you would need to provide a method like this also for B if there will be a class C : B, I ...但是如果有一个class C : B, I你也需要为B提供一个这样的方法class C : B, I ......

It is possible using reflection.可以使用反射。
The code follows.代码如下。 I added caching as a basic optimization, but it can be optimized further by using Delegate.CreateDelegate on methodInfo .我添加了缓存作为基本优化,但可以通过在methodInfo上使用Delegate.CreateDelegate进一步优化。 Also, parameter count and type checks can be added using methodInfo.GetParameters() .此外,可以使用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 is the source of my inspiration. 这里是我的灵感来源。

You can't call Explicit interface method in base class,here i solved this issue你不能在基类中调用显式接口方法,我在这里解决了这个问题

I have two interface -> Interface1 and Interface2我有两个接口 - > Interface1 和 Interface2

public interface Interface1
{      
    string method2();      
}

public interface Interface2
{   
    string method22();

}

Main class Method主类方法

class Program
{
    static void Main(string[] args)
    {

        class1 cls = new class1();
        string str = cls.method2();
    }
}

and my interface implemented class和我的接口实现类

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

Here is my version of Roland Pihlakas's nice solution.这是我的 Roland Pihlakas 很好的解决方案版本。 This version supports the entire inheritance chain instead of immediate base class.此版本支持整个继承链而不是直接基类。 The Invoke method includes additional parameters and there is a void type Invoke for non-function methods. 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);
}

it is necessary explicitly?... Can you use an abstract class or class instead of interface?有必要明确吗?...你可以使用抽象类或类而不是接口吗?

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

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

I have no idea its not possible call base method when it comes from implementation of interface.我不知道当它来自接口的实现时它不可能调用基方法。

On option would be to create a base class that doesn't excplicitly implement an interface, and to only implement the interface on the subclass.一个选项是创建一个不明确实现接口的基类,并且只在子类上实现接口。

public class MyBase
{
    public void MethodA()
    {
        //Do things
    }
}

public interface IMyInterface
{
    void MethodA();
    void MethodB();
}


public class MySub: MyBase, IMyInterface
{
    public void MethodB()
    {
        //Do things
    }
}

Doing this will allow you to access the base classes MethodA without having to implemnet it in MySyb.这样做将允许您访问基类 MethodA,而无需在 MySyb 中实现它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM