Вызывать производные методы класса из базового абстрактного класса (отражение)
Рассмотрим следующую ситуацию -
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