У нас есть следующая ситуация:
public interface IHandle<T> {
void Handler(T param);
}
public abstract class AbsBase : IWasLeftOutForBrevity {
public void SomeFunction<T>(T param) {
// ... see question ...
}
}
public class Derived : AbsBase, IHandle<int>, IHandle<decimal> {
public void Handler(int param) {
// ...
}
public void Handler(decimal param) {
// ...
}
}
В приведенном выше коде это, вероятно, хорошо видимый фрагмент кода, в котором производный класс реализует количество функций-дескрипторов данного типа.
У нас есть универсальный контейнер IoC, который внедряет экземпляры IWasLeftOutForBrevity
и обычно вызывает SomeFunction
в абстрактном базовом классе с заданным типом.SomeFunction
предназначен для вызова связанной функции Handler
класса Derived
как части его операции.
Учитывая, что базовый интерфейс - IWasLeftOutForBrevity
, и мы используем его в общей инфраструктуре,у нас нет прямого доступа к Handler
методам.
Обычно мы делаем что-то вроде:
GetType().InvokeMember("Handler",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
null,
this,
args
);
или аналогичный GetType().GetMethods("Handler", ...)
/ GetType().GetMethod("Handler", ...)
, чтобы найти методдля вызова экземпляра.
Дополнительным «осложнением» является то, что тип, используемый в IHandle
, часто является реализацией общего интерфейса.
Мне было интересно, есть ли более чистый способдоступа к методам Handler
без такого отражения (например, попытка уйти от волшебной строки «Обработчик»), которая более безопасна для типов?
Обновление
У нас нетбыл в состоянии использовать параметры приведения (this is IHandle<T> handle
).Существует поток процессов, который использует общий интерфейс верхнего уровня для передачи данных.Затем вызывается AbsBase.SomeFunction
с интерфейсом верхнего уровня, и приведение прерывается, потому что производный класс не реализует интерфейс верхнего уровня.
т.е.
public interface IDataAbstraction { }
public class SomeFunctionalHandle : IDataAbstraction { }
public class Derived : AbsBase, IHandle<SomeFunctionalHandle>{
public void Handler(SomeFunctionalHandle param) {
// ...
}
}
// later in a decorator
IWasLeftOutForBrevity instance = getInstance(); // get instance of derived
IDataAbstraction data = getData(); // get data based on IDataAbstraction
instance.SomeFunction(data);
В общей инфраструктуре сервисакод проходит вокруг IDataAbstraction
и затем передает его SomeFunction
.