Вызывать производные методы класса из базового абстрактного класса (отражение)

Рассмотрим следующую ситуацию -

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

Могу ли я вызвать метод xx, используя Derived.InvokeX (ParamX)?

Я знаю, что могу сделать что-то вроде этого (проверено, когда InvokeX находится в производном классе, а не shure для абстрактного):

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

но я ищу более быстрые решения. Могу ли я каким-либо образом использовать пространство имен System.Runtime.CompilerServices и, в частности, класс CallSite?

Благодарю.

1 ответ

Решение

У вас есть экземпляр проблемы выражений, проблема расширяемости, распространенная сегодня в большинстве языков программирования. Отражение или динамический вызов - способ обойти это, но он подвержен ошибкам, так как вы не заметите ошибку в именовании или типах параметров, пока не выполните код по указанному пути.

Вы хотите расширить свое приложение для поддержки большего количества типов (больше реализаций IParametr), а также больше операций (в этом случае больше методов, использующих типы параметров).

Таким образом, в основном вы получите матрицу типов и операций. Например

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

X представляют собой требование реализации в типе (столбце) операции (строке).

Чтобы сохранить тип реализации в безопасности, вам нужно использовать шаблон Visitor или Interpreter. У каждого есть свои недостатки.

Шаблон посетителя, использующий двойную рассылку:

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

Другие вопросы по тегам