Надеюсь, я правильно понимаю проблему, и мне было любопытно попробовать заставить ее работать, и я ни в коем случае не эксперт по Unity, но я думал о решении, которое немного проще в реализации и также будет проще сделать с другим контейнером. Казалось бы, единственный способ поддержать открытый универсальный и другие типы - это иметь 2 отдельных контейнера (1 для открытого универсального) и один для ваших командных обработчиков, это может быть не лучшим способом, но это работает с Unity и я предполагаю, что с другими тоже будет легче.
Итак, я придумал это:
Я создал контейнеры следующим образом (вы можете использовать свой традиционный подход, все еще не уверенный для контейнера обработчика)
var container = new UnityContainer();
var container2 = new UnityContainer();
container2.RegisterType(typeof(ICommandHandler<QueryCommand>),
typeof(QueryCommandHandler));
container.RegisterInstance("Handlers", container2);
container.RegisterInstance(container);
container.RegisterType(typeof(ICommandHandler<>),
typeof(DecoratedHandler<>));
В качестве именованного экземпляра вы видите контейнер 2, содержащий обработчики.
Тогда я просто создал базовый базовый класс декоратора в соответствии с требованием шаблона:
public class DecoratorCommandHandler<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> inner;
public DecoratorCommandHandler(
ICommandHandler<TCommand> inner)
{
this.inner = inner;
}
public virtual void Handle(TCommand command)
{
this.inner.Handle(command);
}
}
Во-вторых, я создал еще один универсальный обработчик, который обернул бы все декорации, которые вы хотите сделать для своего решения, здесь вы добавите декорирование для TryCatch / Caching / Transactions или все, что вы хотите применить к каждому обработчику команд:
public class DecoratedHandler<TCommand>
: DecoratorCommandHandler<TCommand>
{
public DecoratedHandler(UnityContainer container)
: base(BuildInner(container))
{
}
private static ICommandHandler<TCommand> BuildInner(
UnityContainer container)
{
var handlerContainer =
container.Resolve<UnityContainer>("Handlers");
var commandHandler =
handlerContainer.Resolve<ICommandHandler<TCommand>>();
return new TryCatchCommandHandler<TCommand>(commandHandler);
}
}
Вы заметите, что первый внутренний разрешает фактический обработчик команд в соответствии с тем, который вы запрашивали, например QueryCommandHandler
, UpdateCommandHandler
, ExecuteCommandHandler
или любым другим, имеющим дело со спецификой. А затем оборачивается всеми декораторами, которые вы хотите использовать для всех из них.
Тогда я смог найти правильный обработчик, оформленный в правильном виде:
ICommandHandler<QueryCommand> handler =
container.Resolve<ICommandHandler<QueryCommand>>();
var cmd = new QueryCommand();
handler.Handle(cmd);
Надеюсь, это поможет