У меня есть проект, в котором используется соглашение о декораторе, чтобы обернуть обработчики команд с помощью декораторов журналов путем перехвата открытых общих типов в StructureMap 2.6. Тем не менее, мне трудно понять, как реализовать эквивалентную функциональность в StructureMap 3, чтобы я мог завершить обновление.Перехват декоратора с открытыми дженериками в StructureMap 3
Вот код от StructureMap 2.6. Во-первых, в моем классе IoC У меня есть политики сканирования, созданной для разрешения обработчики команд:
scan.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
Далее, у меня есть декоратора конвенции, который добавляется к конвенциям сканирующих МОК, что провода до декоратора перехвата:
public class CommandLoggingDecoratorConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
var interfaceTypes = type.GetInterfaces();
foreach (var interfaceType in interfaceTypes)
{
if (interfaceType.IsGenericType
&& interfaceType.GetGenericTypeDefinition() == typeof(ICommandHandler<>))
{
var arguments = interfaceType.GetGenericArguments();
var closedType = typeof(CommandHandlerLoggingDecorator<>)
.MakeGenericType(arguments);
registry.For(interfaceType)
.EnrichWith((c, p) => Activator.CreateInstance(
closedType,
p,
c.GetInstance<IMessageLoggingHelper>(),
c.GetInstance<ILog>()));
}
}
}
}
Тогда мы имеем команду шины, которая отображает конкретную команду обработчика команд и вызывает метод Execute на лесозаготовительной декоратора (который оборачивает обработчик команд), который в свою очередь вызывает метод Execute по команде внутри декоратора:
public class CommandBus : ICommandBus
{
public static IContainer Container;
public void Execute(ICommand command)
{
var handlerType = typeof (ICommandHandler<>)
.MakeGenericType(command.GetType());
dynamic handler = Container
.GetAllInstances(handlerType)
.Cast<dynamic>()
.Single();
handler.Execute((dynamic) command);
}
}
Я смог выполнить эту работу в StructureMap 3, заменив мое соглашение о декораторе политикой перехватчика и добавив политику перехватчика в классе IoC.
Вот политика перехватчик:
public class CommandLoggingDecoratorPolicy : IInterceptorPolicy
{
public string Description { get; private set; }
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (pluginType == typeof (ICommandHandler<>))
yield return new DecoratorInterceptor(
typeof(ICommandHandler<>),
typeof(CommandHandlerLoggingDecorator<>));
}
А вот код, который добавляет к политике перехватчиков МОК:
x.Policies.Interceptors(new CommandLoggingDecoratorPolicy());
Однако, когда я называю Container.GetInstance (в моем CommandBus) его возвращает совпадающую реализацию Command Handler вместо декоратора Command Logging. Если я вызываю Container.GetAllInstances, он возвращает как реализацию (первый), так и декоратор (второй).
Итак, прямо сейчас, единственный способ, которым я могу выполнить эту работу, - это если я либо явно выбираю второй элемент, возвращаемый из Container.GetAllInstances, либо фильтрует результаты и выбирает декоратор, используя отражение. Вот пример:
public class CommandBus : ICommandBus
{
public static IContainer Container;
public void Execute(ICommand command)
{
var handlerType = typeof (ICommandHandler<>)
.MakeGenericType(command.GetType());
var handlers = Container
.GetAllInstances(handlerType)
.Cast<dynamic>();
var handler = handlers.ToList()[1];
handler.Execute((dynamic) command);
}
}
Однако это кажется довольно уродливым решением. Очевидно, должно быть что-то, что мне не хватает. Во-первых, почему Container.GetInstance возвращает реализацию, а не декоратор, когда я явно добавил политику перехвата декоратора? Во-вторых, есть ли лучший способ, которым я должен это делать?
Любые идеи или предложения были бы высоко оценены!
StructureMap 3 имеет [большую поддержку для декораторов] (https://stackoverflow.com/вопросы/30841303/определить фильтр-для-decorateallwith-методом-в-структуры-карта-3). Почему бы вам не использовать декоратор вместо перехватчика? Это делает ваш код более чистым, более ремонтопригодным и устраняет необходимость того, чтобы ваш декоратор зависел от стороннего инструмента (в этом случае библиотека перехвата). – Steven
@Steven Я предполагаю, что это просто непонимание терминологии, но то, что я пытаюсь сделать, - это перехват через инфраструктуру инъекции зависимостей, чтобы обернуть обработчик команд с помощью декоратора. Однако я не пытался перехватить аспектно-ориентированную структуру программирования.Надеюсь, это устранит любую путаницу. Если нет, мне может понадобиться дополнительная информация, чтобы понять, что вы предлагаете. –
А теперь я вижу «CommandHandlerLoggerDecorator». В таком случае, пожалуйста, продолжайте то, что вы делаете. –
Steven