Замок-перехватчик: как добавить перехватчик для всех зарегистрированных типов? - PullRequest
1 голос
/ 13 апреля 2011

Я регистрирую несколько типов по одному:

container.Register(
     Component.For<IService1>().ImplementedBy<ServiceImpl1>(),
     Component.For<IService2>().ImplementedBy<ServiceImpl2>(),
     Component.For<IService3>().ImplementedBy<ServiceImpl3>(),
     Component.For<IService4>().ImplementedBy<ServiceImpl4>()
     );

Есть ли способ зарегистрировать перехватчик для всех зарегистрированных типов этой сборки?Я не хочу регистрировать все типы по соглашению, как AllTypes.Я просто хотел бы добавить перехватчик без записи

.Interceptors(InterceptorReference.ForType<DummyInterceptor>())
            .SelectedWith(new FooInterceptorSelector()).Anywhere

миллиардов раз.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Как и , предложенное Дэном , это может быть достигнуто с помощью пользовательских Составителей конструирования ComponentModel .

Сначала обратите внимание, что

...
    .Interceptors(InterceptorReference.ForType<DummyInterceptor>())
        .SelectedWith(new FooInterceptorSelector())
        .Anywhere

в основном эквивалентно

...
    .SelectInterceptorsWith(new FooInterceptorSelector())
    .Interceptors(InterceptorReference.ForType<DummyInterceptor>())
        .Anywhere

, то есть ассоциирование IInterceptorSelector с ComponentModel не зависит от регистрации перехватчиков, которые будут выбраны с помощью IInterceptorSelector.Более того, у каждого ComponentModel может быть только один селектор-перехватчик.

Из-за этого разделения лучше всего решить проблему, используя два независимых участника - один для регистрации перехватчиков, а другой для регистрации селектора перехватчика.

Первый в основном такой же, как показано в Ответ Дана .Однако нет необходимости добавлять DependencyModel для перехватчика, поскольку перехватчик уже должен был быть зарегистрирован в контейнере, используя что-то вроде

container.Register(Component.For<DummyInterceptor>().LifestyleTransient());

, чтобы он мог выглядеть примерно как

using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.ModelBuilder;

...

public class InterceptorContributor : IContributeComponentModelConstruction
{
    private readonly InterceptorReference interceptor;

    public InterceptorContributor(InterceptorReference interceptor)
    {
        this.interceptor = interceptor;
    }

    public void ProcessModel(IKernel kernel, ComponentModel model)
    {
        if (...)
        {
            model.Interceptors.Add(interceptor)
        }
    }
}

или если вы хотите иметь возможность зарегистрировать несколько перехватчиков за один раз, можно воспользоваться существующей реализацией InterceptorDescriptor и вместо этого сделать:

using System;

using Castle.Core;
using Castle.MicroKernel;
using Castle.MicroKernel.ModelBuilder;
using Castle.MicroKernel.ModelBuilder.Descriptors;

...

public class InterceptorsContributor : IContributeComponentModelConstruction
{
    private readonly Predicate<ComponentModel> predicate;
    private readonly IComponentModelDescriptor interceptorsDescriptor;

    public InterceptorsContributor(Predicate<ComponentModel> predicate, params InterceptorReference[] interceptors)
    {
        this.predicate = predicate ?? throw new ArgumentNullException(nameof(predicate));
        interceptorsDescriptor = new InterceptorDescriptor(interceptors);
    }

    public void ProcessModel(IKernel kernel, ComponentModel model)
    {
        if (predicate.Invoke(model))
        {
            interceptorsDescriptor.BuildComponentModel(kernel, model);
            interceptorsDescriptor.ConfigureComponentModel(kernel, model);
        }
    }
}

Для регистрацииIInterceptorSelector, вкладчик может быть реализован либо с помощью того, что делает InterceptorSelectorDescriptor:

public void ProcessModel(IKernel kernel, ComponentModel model)
{
    if (...)
    {
        var options = model.ObtainProxyOptions();
        options.Selector = new InstanceReference<IInterceptorSelector>(selector);
    }
}

, либо с помощью InterceptorSelectorDescriptor напрямую:

using System;

using Castle.Core;
using Castle.DynamicProxy;
using Castle.MicroKernel;
using Castle.MicroKernel.ModelBuilder;
using Castle.MicroKernel.ModelBuilder.Descriptors;

...

public class InterceptorSelectorContributor : IContributeComponentModelConstruction
{
    private readonly Predicate<ComponentModel> predicate;
    private readonly IComponentModelDescriptor interceptorSelectorDescriptor;

    public InterceptorSelectorContributor(Predicate<ComponentModel> predicate, IInterceptorSelector selector)
    {
        this.predicate = predicate ?? throw new ArgumentNullException(nameof(predicate));

        var selectorRef = new InstanceReference<IInterceptorSelector>(selector);
        interceptorSelectorDescriptor = new InterceptorSelectorDescriptor(selectorRef);
    }

    public void ProcessModel(IKernel kernel, ComponentModel model)
    {
        if (predicate.Invoke(model))
        {
            interceptorSelectorDescriptor.BuildComponentModel(kernel, model);
            interceptorSelectorDescriptor.ConfigureComponentModel(kernel, model);
        }
    }
}
0 голосов
/ 28 октября 2011

Как бы вы указали .SelectedWith при использовании вкладчика ComponentModel? Для этого я могу добавить перехватчик для всех методов.

public class MyContributor : IContributeComponentModelConstruction 
{
    public void ProcessModel(IKernel kernel, ComponentModel model)
    {
        model.Dependencies.Add(new DependencyModel(DependencyType.Service, null, typeof(MyInterceptor), false));
        model.Interceptors.AddFirst(InterceptorReference.ForType<MyInterceptor>());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...