开发者

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 to MsgAHandler, MsgHandler and ObjectHandler.
  • If I receive a IMsg, I should dispatch it to MsgHandler and ObjectHandler.
  • 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); }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜