Как и , предложенное Дэном , это может быть достигнуто с помощью пользовательских Составителей конструирования 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);
}
}
}