从基本抽象类调用派生类方法(反射)

时间:2014-02-13 23:45:19

标签: c# reflection abstract-class invokemember

考虑下一个情况 -

public class Derived : Base{
   X(ParamX){}   // xx method
   X(ParamY){}   // xy
}

public abstract class Base {
   InvokeX(IParametr param){
      ...some magic
   }
}

public class ParamX : IParametr {}
public class ParamY : IParametr {}

我可以使用 Derived.InvokeX(ParamX)调用xx方法吗?

我知道我可以做这样的事情(当 InvokeX 在派生类中时检查,而不是抽象的shure):

InvokeX(IParametr @param){
    ((dynamic) this).X((dynamic) @param);
}

但我正在寻找更快的解决方案。我可以以某种方式使用System.Runtime.CompilerServices命名空间,特别是CallSite Class吗?

感谢。

1 个答案:

答案 0 :(得分:2)

您有Expression Problem的实例,这是当今大多数编程语言中常见的可扩展性问题。反射或动态调用是一种解决方法,但它很容易出现错误,因为在您按照特定路径运行代码之前,您不会注意到命名或参数类型的错误。

您希望扩展您的应用程序以支持更多类型(更多IParametr的实现)以及更多操作(在这种情况下,使用参数类型的更多方法)。

所以基本上你会得到一个类型和操作的矩阵。 E.g。

Type     Derived     Derived2   ...
ParamX     x            x
ParamY                  x
...

Xes表示要求在操作(行)的类型(列)中实现。

要确保实现类型安全,您需要使用Visitor或Interpreter模式。每个都有它的缺点。

访客模式,使用double dispatch

public class Derived : Base {
    public override void X(ParamX x) { }
    public override void X(ParamY a) { }
}

public abstract class Base : IXVisitor
{
    public void Visit(IParametr parameter)
    {
        parameter.Accept(this);
    }
    public abstract void X(ParamX x);
    public abstract void X(ParamY a);
}

public interface IXVisitor
{
    void X(ParamX a);
    void X(ParamY a);
}

public interface IParametr
{
    void Accept(IXVisitor visitor);
}

public class ParamX : IParametr
{
    public void Accept(IXVisitor visitor)
    {
        visitor.X(this);
    }
}

public class ParamY : IParametr
{
    public void Accept(IXVisitor visitor)
    {
        visitor.X(this);
    }
}

如果您想获得真正的铁杆,可以尝试Object Algebras