我们有以下情况:
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
的实例,并在给定类型的抽象基类上通用地调用SomeFunction
。 SomeFunction
用于在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
。
答案 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首先在评论中建议了这一点,而我仍在尝试反射。