1

考虑下一种情况——

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在派生类中时检查,而不是抽象的舒尔):

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

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

谢谢。

4

1 回答 1

2

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

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

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

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

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

为了保证实现类型的安全,您需要使用访问者或解释器模式。每个都有其缺点。

访问者模式,使用双重调度

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

如果您想获得真正的硬核,可以尝试对象代数

于 2014-02-14T00:28:34.933 回答