Castle Windsor Proxy для интерфейса без цели - PullRequest
0 голосов
/ 31 октября 2010

У меня есть WindsorContainer с IModelInterceptorsSelector.Он работает хорошо, за исключением компонентов, которые не имеют реализации (например, все поведение динамически обрабатывается IInterceptor).

Если я пытаюсь разрешить компонент только с помощью интерфейса, я получаю:

Castle.MicroKernel.ComponentActivator.ComponentActivatorException occurred
  Message=Could not find a public constructor for type ConsoleApplication1.IInterfaceOnlyService. Windsor can not instantiate types that don't expose public constructors. To expose the type as a service add public constructor, or use custom component activator.
  Source=Castle.Windsor
  StackTrace:
       at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.FastCreateInstance(Type implType, Object[] arguments, Type[] signature)

Но если я вручную укажу перехватчик во время регистрации, он будет работать нормально.Это ошибка в Виндзоре или я что-то не так делаю?

Код для воспроизведения довольно прост:

        var container = new WindsorContainer();
        container.Kernel.ProxyFactory.AddInterceptorSelector(new Selector());
        container.Register(Component.For<TestInterceptor>());
        container.Register(Component.For<IInterfaceOnlyService>()); // this doesn't work
        // container.Register(Component.For<IInterfaceOnlyService>().Interceptors<TestInterceptor>());  // this works
        var i = container.Resolve<IInterfaceOnlyService>();


    public class Selector : IModelInterceptorsSelector
    {
        public bool HasInterceptors(ComponentModel model)
        {
            return model.Service != typeof (TestInterceptor);
        }

        public InterceptorReference[] SelectInterceptors(ComponentModel model, InterceptorReference[] interceptors)
        {                
            return new[] { InterceptorReference.ForType<TestInterceptor>() };
        }
    }

Спасибо.

1 Ответ

0 голосов
/ 04 ноября 2010

Это определенно похоже на ошибку в Виндзоре.Похоже, это связано с принятием InterceptorGroup для компонентов без цели.То есть:

container.Register(Component.For<IInterfaceOnlyService>  
().Interceptors<TestInterceptor>());

работает.

container.Register(Component.For<IInterfaceOnlyService>  
().Interceptors(InterceptorReference.ForType(typeof(TestInterceptor))));

При взгляде на источник Castle, разница в том, что первый добавляет аддескриптор напрямую:

return this.AddDescriptor(new InterceptorDescriptor<TService>(new  
InterceptorReference[] { new InterceptorReference(typeof(TInterceptor)) }));

Но второй использует внутреннюю группу перехватчиков:

return new InterceptorGroup<TService>((ComponentRegistration<TService>) this,   
interceptors);

Соответственно, это, похоже, ошибка в InterceptorGroups.

Мой обходной путь (хотя и хакерский) - использовать мой LazyComponentLoader для прямого вызова AddDescriptor.

...