I think I figured this out
The fact that the interceptor wasn't being assigned to Test in 2.5.3 is a
bug/feature disguised as a bug. The 3.1.0 behaviour is more correct, and
forces you to be explicit about what you want an interceptor on. Since my
actual code involved a Facility, here is the solution that fixes the issue:
public class Facility : AbstractFacility
{
protected override void Init() { Kernel.ComponentRegistered +=
KernelComponentRegistered; }
static void KernelComponentRegistered(string key, IHandler handler)
{
if
(typeof(IInterceptor).IsAssignableFrom(handler.ComponentModel.Implementation))
return; //This is so that interceptors don't intercept themselves
* if (handler.ComponentModel.Services.FirstOrDefault() ==
typeof(Test)) return; //This is so that the interceptor does not intercept
our Factory-initialized class*
handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForKey("SomeInterceptor"));
}
}
On Friday, 28 September 2012 01:34:11 UTC-7, Nik Pinski wrote:
>
> The following code passes as-is with Castle.Windsor 2.5.3 but fails after
> upgrading to 3.1.0
>
> The exception is an InvalidProxyConstructorArgumentsException and it
> states "Can not instantiate proxy of class: Test. Could not find a
> parameterless constructor."
>
> static void Main(string[] args)
> {
> var container = new WindsorContainer();
> container.Register(Component.For<Interceptor>(),
> Component.For<Test>().UsingFactoryMethod(()
> => new Test(""))
>
> .Interceptors<Interceptor>());
>
> var test = container.Resolve<Test>(); //THROWS IN 3.1.0
> }
> }
>
> public class Test
> {
> public readonly string S;
>
> public Test(string s)
> {
> S = s;
> }
> }
>
> public class Interceptor : IInterceptor
> {
> public void Intercept(IInvocation invocation)
> {
> invocation.Proceed();
> }
> }
>
>
> In my real code Test is a MongoDatabase that is being constructed using a
> factory method and injected into a Repository.
>
> In my real code I'm also using an inheritor to an AbstractFacility to
> register the interceptor. This way I don't have to register the interceptor
> for each component. Both forms of interceptor usage seem to work/fail (in
> 2.5.3/3.1.0) the same way on later resolution. For reference here is a
> shortened version of the facility:
>
> public class Facility : AbstractFacility
> {
> protected override void Init() { Kernel.ComponentRegistered +=
> KernelComponentRegistered; }
>
> static void KernelComponentRegistered(string key, IHandler handler)
> {
> if
> (typeof(IInterceptor).IsAssignableFrom(handler.ComponentModel.Implementation))
>
> return;
>
> handler.ComponentModel.Interceptors.AddIfNotInCollection(InterceptorReference.ForKey("SomeInterceptor"));
> }
> }
>
> I looked at the Castle.Windsor source code and the throwing code is
> expecting to wrap a proxy around the class it is given which is why it's
> looking for a parameterless constructor. However in 2.5.3 I think the
> proxy generation code never got executed and the container resolves
> (correctly in my mind) to a non-proxy version of Test/MongoDatabase
>
>
> So two questions I guess:
> 1) What's changed?
> 2) How do I keep my interceptor registration without generating a proxy
> for the object resolved by the factory method? Or I guess how does a proxy
> get generated using a factory method for the component...
>
--
You received this message because you are subscribed to the Google Groups
"Castle Project Users" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/castle-project-users/-/Gduk02SkKiYJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-users?hl=en.