Сегодня мы пошли по интересному пути после прочтения этой статьи о декорировании обработчиков команд а>. Я хотел посмотреть, смогу ли я реализовать шаблон с помощью Unity вместо SimpleInjector, и пока это оказалось чрезвычайно сложно.
Первое, что мне нужно было сделать, это установить UnityAutoRegistration, чтобы разрешить открытый универсальный интерфейс ICommandHandler<TCommand>
. Текущее решение для этого аспекта выглядит следующим образом:
Container = new UnityContainer().LoadConfiguration();
Container.ConfigureAutoRegistration()
.ExcludeSystemAssemblies()
.Include(type => type.ImplementsOpenGeneric(typeof(ICommandHandler<>)),
(t, c) => c.RegisterType(typeof(ICommandHandler<>), t)
)
.ApplyAutoRegistration()
;
Это работает для первой части, разрешая любой отдельный ICommandHandler<TCommand>
. До сих пор разочаровывала реализация обработчика оформления. Как только я добавляю второй ICommandHandler<TCommand>
в качестве декоратора, Unity генерирует исключение StackOverflowException. Я недостаточно разбираюсь в внутренностях Unity, но я предполагаю, что это потому, что он не может понять, к какому экземпляру обращаться — к обработчику команд или декоратору обработчика команд — поскольку оба реализуют интерфейс ICommandHandler<TCommand>
.
Поиск в Google привел меня сначала к этой статье, в которой объясняется, как это сделать так, как я хотел бы. рассмотреть метод грубой силы. Я также нашел эти related pages, но ни одна из них не является полным решением моей проблемы (и я слишком невежественен, чтобы понять это самостоятельно).
Затем я нашел эту статью, которая, кажется, решает мои проблемы . Однако мощное решение не учитывает работу с открытыми дженериками. В настоящее время большинство наших зависимостей загружаются из раздела единства в файле .config, поэтому я не хочу писать тонну скомпилированного кода для каждого обработчика или декоратора. Кажется, что иметь какой-то UnityContainerExtension и DecoratorBuildStrategy - правильный путь, но я не могу понять это. Я уже некоторое время играю с кодом мускулистого, и я полностью застрял. Мои попытки изменить его код для учета дженериков привели к BadImageFormatExceptions (была предпринята попытка загрузить программу с неправильным форматом. (Исключение из HRESULT: 0x8007000B)).
Мне нравится идея сделать это для реализации цепочки декораторов, потому что она короткая, и на каждую проблему приходится только 1 строка:
var container = new Container();
// Go look in all assemblies and register all implementations
// of ICommandHandler<T> by their closed interface:
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
// Decorate each returned ICommandHandler<T> object with an
// TransactionCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// Decorate each returned ICommandHandler<T> object with an
// DeadlockRetryCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>));
... но я не хочу менять свой контейнер с Unity на Simple Injector, если мне это не нужно.
Итак, мой вопрос: как я могу реализовать открытую общую цепочку декораторов, используя единство (плюс UnityAutoRegistration
)?