温莎拦截器异常
我有一个 Windsor 容器,正在使用 InterceptorSelector 和 LazyComponentLoader。
我的 InterceptorSelector 返回一个 InterceptorReference 到我的 InterceptorAdapter 类,看起来像这样
public class InterceptorAdapter<T> : Castle.DynamicProxy.IInterceptor, IOnBehalfAware where T : IMyType
{
private readonly T interceptor;
public InterceptorAdapter(T interceptor)
{
this.interceptor = interceptor;
}
....
}
,所以 InterceptorSelector
public InterceptorReference[] SelectInterceptors(ComponentModel model, InterceptorReference[] interceptors)
{
var results = new List<InterceptorReference>();
....
foreach (var interceptorType in someInterceptorTypes)
{
Type interceptorAdapterType = typeof(InterceptorAdapter<>).MakeGenericType(interceptorType);
if (kernel.GetHandler(interceptorAdapterType) == null)
{
// need to do this or Castle complains it can't create my
// interceptor...I guess LazyComponentLoaders don't work for InterceptorReferences?...
// I suspect the problem may be here...
kernel.Register(lazyComponentLoader.Load(null, interceptorAdapterType, null));
}
results.Add(InterceptorReference.ForType(interceptorAdapterType));
}
return results.ToArray();
}
在我的 InterceptorSelector 第一次返回 InterceptorReference 时工作得很好。下次,当它使用不同的泛型类型参数将 InterceptorReference 返回到 InterceptorAdapter 时,我得到
Castle.MicroKernel.ComponentRegistrationException occurred
Message=There is a component already registered for the given key interceptor
Source=Castle.Windsor
StackTrace:
at Castle.MicroKernel.SubSystems.Naming.DefaultNamingSubSystem.Register(String key, IHandler handler) in c:\TeamCity\buildAgent\work\1ab5e0b25b145b19\src\Castle.Windsor\MicroKernel\SubSystems\Naming\DefaultNamingSubSystem.cs:line 75
InnerException:
My LazyComponentLoader 只是
public IRegistration Load(string key, Type service, IDictionary arguments)
{
ComponentRegistration<object> component = Component.For(service).Named(key);
if (arguments != null)
{
// merge is an extension method to merge dictionaries.
component.DynamicParameters((k, d) => d.Merge(arguments));
}
return component;
}
我的容器设置看起来像
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.AddFacility("factories", new FactorySupportFacility());
container.Register(Component.For<ILazyComponentLoader>().ImplementedBy<MyLazyComponentLoader>().LifeStyle.Singleton);
container.Kernel.ProxyFactory.AddInterceptorSelector(new InterceptorSelector(container.Kernel, container.Resolve<ILazyComponentLoader>()));
有什么建议吗?
谢谢!
I have a Windsor container that I'm using an InterceptorSelector and a LazyComponentLoader with.
My InterceptorSelector returns an InterceptorReference to my InterceptorAdapter class that looks like this
public class InterceptorAdapter<T> : Castle.DynamicProxy.IInterceptor, IOnBehalfAware where T : IMyType
{
private readonly T interceptor;
public InterceptorAdapter(T interceptor)
{
this.interceptor = interceptor;
}
....
}
so the InterceptorSelector does
public InterceptorReference[] SelectInterceptors(ComponentModel model, InterceptorReference[] interceptors)
{
var results = new List<InterceptorReference>();
....
foreach (var interceptorType in someInterceptorTypes)
{
Type interceptorAdapterType = typeof(InterceptorAdapter<>).MakeGenericType(interceptorType);
if (kernel.GetHandler(interceptorAdapterType) == null)
{
// need to do this or Castle complains it can't create my
// interceptor...I guess LazyComponentLoaders don't work for InterceptorReferences?...
// I suspect the problem may be here...
kernel.Register(lazyComponentLoader.Load(null, interceptorAdapterType, null));
}
results.Add(InterceptorReference.ForType(interceptorAdapterType));
}
return results.ToArray();
}
Things work great the first time my InterceptorSelector returns an InterceptorReference. The next time, when it returns an InterceptorReference to an InterceptorAdapter with a different generic type argument, I get
Castle.MicroKernel.ComponentRegistrationException occurred
Message=There is a component already registered for the given key interceptor
Source=Castle.Windsor
StackTrace:
at Castle.MicroKernel.SubSystems.Naming.DefaultNamingSubSystem.Register(String key, IHandler handler) in c:\TeamCity\buildAgent\work\1ab5e0b25b145b19\src\Castle.Windsor\MicroKernel\SubSystems\Naming\DefaultNamingSubSystem.cs:line 75
InnerException:
My LazyComponentLoader simply does
public IRegistration Load(string key, Type service, IDictionary arguments)
{
ComponentRegistration<object> component = Component.For(service).Named(key);
if (arguments != null)
{
// merge is an extension method to merge dictionaries.
component.DynamicParameters((k, d) => d.Merge(arguments));
}
return component;
}
My container setup looks like
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.AddFacility("factories", new FactorySupportFacility());
container.Register(Component.For<ILazyComponentLoader>().ImplementedBy<MyLazyComponentLoader>().LifeStyle.Singleton);
container.Kernel.ProxyFactory.AddInterceptorSelector(new InterceptorSelector(container.Kernel, container.Resolve<ILazyComponentLoader>()));
Any suggestions?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这似乎是 Castle 使用 LazyComponentLoader 解析拦截器的方式存在问题。
更改选择器中的代码以执行以下操作:
似乎可以解决问题。
This seems to be a problem in the way Castle resolves Interceptors using an LazyComponentLoader.
Changing my code in the selector to do:
Seems to fix the problem.