我有一种情况,其中两个类(一个派生自另一个)都明确地实现了相同的接口:
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; }
}
我也可以更改它以非显式地实现接口。但我只是想知道是否有可能没有任何这些解决方法。
答案 0 :(得分:20)
不幸的是,这是不可能的。
甚至没有辅助方法。辅助方法与第二次尝试具有相同的问题:this
类型为B
,即使在基类中也会调用M
中的B
实现:< / p>
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
的{{1}}实施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
提供这样的方法
答案 1 :(得分:10)
可以使用反射。
代码如下。我将缓存添加为基本优化,但可以使用Delegate.CreateDelegate
上的methodInfo
进一步优化缓存。此外,可以使用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是我灵感的源泉。
答案 2 :(得分:0)
有必要明确吗?...你能使用抽象类或类而不是接口吗?
interface ISample {}
class A : ISample {}
class B : A {}
...
base.fun();
...
http://msdn.microsoft.com/en-us/library/hfw7t1ce(v=vs.71).aspx
当它来自接口的实现时,我不知道它不可能的调用基础方法。
答案 3 :(得分:0)
你不能在基类中调用显式接口方法,这里我解决了这个问题
我有两个界面 - &gt; 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
}
答案 4 :(得分: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();
}
}
}
答案 5 :(得分: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);
}
答案 6 :(得分:0)
On选项将创建一个不完全实现接口的基类,而仅在子类上实现该接口。
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
}
}
这样做将允许您访问基类MethodA,而不必在MySyb中对其进行标记。