Make Unity resolve implementations considering contravariance
I want to use unity for a polymorphic event aggregation/handling where handlers are registered through the container.
Handlers declares a generic parameter with the "in" modifier, since it's only used as an input parameter. So the parameter is contravariant.
Considering the following sample.
interface IHandler&开发者_如何学Pythonlt;in T> { void Handle(T message); }
interface IMsg { string Message { get; } }
class MsgA : IMsg { ... }
class MsgB : IMsg { ... }
class MsgAHandler : IHandler<MsgA> {
public void Handle(MsgA msg) { ... }
}
class MsgBHandler : IHandler<MsgB> {
public void Handle(MsgB msg) { ... }
}
class MsgHandler : IHandler<IMsg> {
public void Handle(IMsg msg) { ... }
}
class ObjectHandler : IHandler<object> {
public void Handle(object msg) { ... }
}
class Events {
public void Publish<T>(T message) {
// Actually this code is more complex for Unity, because it first tries to
// resolve the default registered component using .Resolve(),
// then use .ResolveAll() to resolve all named components
foreach (var handler in this.container.ResolveAll<IHandle<T>>()) {
handler.Handle(message);
}
}
}
My expectations are the followings :
- If I receive a
MsgA
, I should dispatch it toMsgAHandler
,MsgHandler
andObjectHandler
. - If I receive a
IMsg
, I should dispatch it toMsgHandler
andObjectHandler
. ObjectHandler
should receive all messages.
By default, Castle Windsor handles correctly this scenario without any specific configuration (tested with v2.5.1).
Does Unity exposes a way to enhance the resolution and allow Resolve<IHandle<MsgA>>()
to also match any type implementing IHandle<IMsg>
or IHandle<object>
?
I've looked for samples using UnityExtensions (matching rules, policies, and so on) without success.
Could someone directs me to the correct mechanism to use to implement a such scenario ?
Could you do:
container.RegisterType(typeof(IHandle<>), typeof(MsgAHandler<>))
But you would probably need to change some of your code for that to work properly. Like:
public interface IHandler<in THandler> where THandler : class, IMsg
{ void Handle(THandler message); }
精彩评论