Заставьте Unity разрешить реализации с учетом контравариантности - PullRequest
2 голосов
/ 03 июня 2011

Я хочу использовать Unity для агрегирования / обработки полиморфных событий, когда обработчики регистрируются через контейнер.

Обработчики объявляют универсальный параметр с модификатором «in», поскольку он используется только как входной параметр.Таким образом, параметр является контрвариантным.

Учитывая следующий образец.

interface IHandler<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);
     }
   }
}

Мои ожидания следующие:

  • Если я получу MsgA, яследует отправить его на MsgAHandler, MsgHandler и ObjectHandler.
  • Если я получу IMsg, я должен отправить его на MsgHandler и ObjectHandler.
  • ObjectHandler должен получать все сообщения.

По умолчанию Castle Windsor правильно обрабатывает этот сценарий без какой-либо конкретной конфигурации (протестировано с v2.5.1).

Предоставляет ли Unity способ улучшенияразрешение и разрешение Resolve<IHandle<MsgA>>() также могут соответствовать любому типу, реализующему IHandle<IMsg> или IHandle<object>?

Я безуспешно искал примеры, использующие UnityExtensions (правила сопоставления, политики и т. д.).*

Может ли кто-нибудь указать мне правильный механизм, который можно использовать для реализации такого сценария?

1 Ответ

1 голос
/ 03 июня 2011

Не могли бы вы сделать:

container.RegisterType(typeof(IHandle<>), typeof(MsgAHandler<>))

Но вам, вероятно, потребуется изменить часть своего кода, чтобы он работал правильно. Как:

public interface IHandler<in THandler> where THandler : class, IMsg
{ void Handle(THandler message); }
...