Question

Consider next situation -

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 {}

Can I invoke xx method using Derived.InvokeX(ParamX) ?

I know that I can do something like this (checked when InvokeX is in derived class, not shure for abstract):

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

but I am looking for more faster solutions. Can I use in some way System.Runtime.CompilerServices namespace and in particular CallSite Class?

Thanks.

Was it helpful?

Solution

You have an instance of the Expression Problem, an extensibility problem common in most programming languages today. Reflection or dynamic invocation is a way around it, but it is prone to bugs, since you will not notice a mistake in naming or parameter types until you run the code down that specific path.

You want to extend your application to support more types (more implementations of IParametr) and also more operations (in this case more methods using types of parameters).

So basically you will get a matrix of types and operations. E.g.

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

The Xes represent requiring the implementation in the type (column) of the operation (row).

To keep the implementation type safe you need to use either the Visitor or the Interpreter pattern. Each has its drawbacks.

The visitor pattern, utilizing 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);
    }
}

If you'd like to get really hardcore you can try Object Algebras

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top