Here are the relevant types and an example of the handler I want linked to IHandle<EventA>
and IHandle<EventB>
:
// marker interface
public interface IEvent {}
public interface IHandle<TEvent> where TEvent : IEvent {
void Handle(TEvent e);
}
public class SomeHandler : IHandle<EventA>, IHandle<EventB> {
public void Handle(EventA e) {}
public void Handle(EventB e) {}
}
I want use the scanner to automatically link SomeHandler as the implementation for both IHandle<EventA>
and IHandle<EventB>
. I don't want to have to manually specify handlers for each event.
Right now I have the following:
public IContainer CreateContainer(params Assembly[] assemblies) {
var container = new Container();
container.Configure(
config => config.Scan(
scanner => {
foreach (var assembly in assemblies) {
scanner.Assembly(assembly);
}
// 1 - begin
scanner.Convention<HandlerConvention>();
// 1 - end
}
)
);
}
and
public class HandlerConvention : IRegistrationConvention {
public void Process(Type type, Registry registry) {
// find all IHandle<> interfaces that this type implements
var interfaces = from t in type.GetInterfaces()
where t.IsGenericType
&& t.GetGenericTypeDefinition()
.IsAssignableFrom(typeof(IHandle<>))
select t;
// register this type for each IHandle<> that it implements
foreach (var i in interfaces) {
registry.AddType(i, type);
}
}
}
At first I tried using scanner.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
instead of using the code in // 1
and the convention. That didn't work. Trying to do it that way assigned SomeHandler
only to the IHandle<EventA>
. It missed assigning it to IHandle<EventB>
.
After digging through the StructureMap code for a bit, I found that it eventually calls an extension method on Type
called FindInterfaceThatCloses(this Type type, Type openType)
. That returns only the first interface implemented by type
that closes openType
instead of all interfaces implemented by type
that close openType
.
Is there a way to do this with less code?