Structuremap возвращает неправильный экземпляр для открытого универсального типа?
Я пытаюсь использовать Structuremap с открытым универсальным, чтобы получить экземпляры обработчика событий во время выполнения, я использую конфигурацию открытого универсального
// #1 Configuration
scan.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
// #2 Actual class
public class EventHandlerClass :
IHandle<MyEvent>,
IHandle<AnotherEvent>,
IHandle<ThirdEvent>,
{
void IHandle<MyEvent>.Handle(MyEvent args)
{
}
void IHandle<AnotherEvent>.Handle(AnotherEvent args)
{
}
void IHandle<ThirdEvent>.Handle(ThirdEvent args)
{
}
}
Мой код работает в тех случаях, когда я запрашиваю зависимость через внедрение в конструктор, как это работает нормально.
public MyClass(IHandle<MyEvent>[] alleventHandlers)
{
}
Однако в одном из моих случаев мне нужно получить зависимость во время выполнения. Ниже приведен код, который я использую
// Code
Type t = typeof(IHandle<>);
MyEvent m = new MyEvent();
var generic = t.MakeGenericType(m.GetType());
dynamic instances = nestedContainer.GetAllInstances(genType) as IEnumerable;
foreach( dynamic inst in instances)
{
inst.Handle(m)
}
Я получаю следующую ошибку. {"Наилучшее перегруженное соответствие метода для 'MyNameSpace.EventHandlerClass.Handle(MyNameSpace.Events.ThirdEvent)' имеет недопустимые аргументы"}
GetAllInstances каким-то образом возвращают объект EventHandlerClass с методом Handle, ожидающим событие ThirdEvent, хотя я вызывал GetAllInstances с правильным типом.
Это ошибка? или я сделал ошибку в конфигурации?
1 ответ
Динамическая переменная имеет доступ только к методам типа (обычно общедоступным, но основывается на контексте). Он не имеет доступа к интерфейсным методам, которые реализованы явно. Единственный способ вызвать явные реализации интерфейса - привести объект к интерфейсу.
Таким образом, у вас есть два варианта: а) реализовать интерфейсы неявно, как предложено @Yacoub, или б) использовать рефлексию для вызова метода.
foreach(dynamic inst in instances)
{
Type type = inst.GetType();
Type interfaceType = type.GetInterfaces().Single(t => t == generic);
interfaceType.GetMethod("Handle").Invoke(inst, new object[] { m });
}