从基础调用派生类函数的实现

时间:2019-02-22 12:29:32

标签: c# reflection interface

我们有以下情况:

public interface IHandle<T> {
 void Handler(T param);
}

public abstract class AbsBase : IWasLeftOutForBrevity {
 public void SomeFunction<T>(T param) {
   // ... see question ...
 }
}

public class Derived : AbsBase, IHandle<int>, IHandle<decimal> {
 public void Handler(int param) {
   // ...
 }
 public void Handler(decimal param) {
   // ...
 }
}

在上面的代码中,这可能是一段很好看的代码,其中派生类实现了给定特定类型的许多句柄函数。

我们有一个通用的IoC容器,该容器注入IWasLeftOutForBrevity的实例,并在给定类型的抽象基类上通用地调用SomeFunctionSomeFunction用于在Handler类上调用关联的Derived函数,作为其操作的一部分。

鉴于基本接口是IWasLeftOutForBrevity,并且我们在通用基础结构中使用了该接口,因此我们无法直接访问Handler方法。

我们通常会做类似的事情:

GetType().InvokeMember("Handler",
 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
 null,
 this,
 args
);

或类似的GetType().GetMethods("Handler", ...) / GetType().GetMethod("Handler", ...)来查找在实例上调用的方法。

增加的“复杂性”是IHandle中使用的类型通常是通用接口的实现。

我想知道是否有更干净的方法来访问Handler方法而不进行这种类型更安全的反射(例如,尝试摆脱魔术的“ Handler”字符串)?

更新

我们无法使用强制转换选项(this is IHandle<T> handle)。有一个使用通用顶级接口传递数据的流程。然后使用顶层接口调用AbsBase.SomeFunction,由于派生类未实现顶层接口,因此转换中断。

public interface IDataAbstraction { }

public class SomeFunctionalHandle : IDataAbstraction { }

public class Derived : AbsBase, IHandle<SomeFunctionalHandle>{
 public void Handler(SomeFunctionalHandle param) {
   // ...
 }
}

// later in a decorator
IWasLeftOutForBrevity instance = getInstance(); // get instance of derived
IDataAbstraction data = getData(); // get data based on IDataAbstraction
instance.SomeFunction(data);

在通用服务基础结构中,代码传递IDataAbstraction,然后传递给SomeFunction

1 个答案:

答案 0 :(得分:0)

我可能会这样做:

public abstract class AbsBase
{
    public void SomeFunction<T>(T param)
    {
        if (this is IHandle<T> handle)
        {
            handle.Handler(param);
        }
        else
        {
            // Handle error case
        }
    }
}

在达到此目的之前,我使用反射和编译表达式使用了其他方法。我认为它们都不如上面的代码,因此我没有将它们包括在我的答案中,但是如果您感兴趣的话,它们也位于编辑历史记录中。

编辑:嗯,事实证明,@ HimBromBeere首先在评论中建议了这一点,而我仍在尝试反射。