2014-02-13 141 views
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

谢谢。

回答

2

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

您希望扩展您的应用程序以支持更多类型(更多实现IParametr)以及更多操作(本例中使用更多参数类型的方法)。

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

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

Xes表示需要在操作(行)的类型(列)中执行。

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

Visitor模式,利用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

相关问题