Search code examples
c#.netcastle-windsorcastle-dynamicproxy

Castle Windsor Proxy Abstract Class with Interface


I have the following scenario:

public interface IFoo 
{
    void Foo1();

    void Foo2(); 
}

public abstract class Foo : IFoo
{
    public void Foo1() { }

    public abstract void Foo2();
}

I want to register a service for IFoo, implemented by Foo, but with an interceptor to handle calls to the non-implemented abstract members. So, I can do:

container.Register(Component.For<IFoo>()
.ImplementedBy<Foo>().Interceptors<MyInterceptor>());

But I get the following exception trying to activate my component:

"Instances of abstract classes cannot be created."

   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, Object[] arguments, Type[] signature)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context)
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired)
   at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
   at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveServiceDependency(CreationContext context, ComponentModel model, DependencyModel dependency)

I've noticed that the following works successfully....

Component.For<Foo>().Forward<IFoo>().Interceptors<MyInterceptor>()

but then my interceptor ends up seeing Foo, not IFoo as the TargetType at interception time...which is not what I want.

Any suggestions on how to accomplish this?

Thanks.


Solution

  • I think if you specify:

    Component.For<IFoo, Foo>().Interceptors<MyInterceptor>()
    

    this will work.

    The reason why you were originally experiencing the issue was because Windsor creates a proxy for the services (which was the interface) not the class (which was not a service) and it tried to instantiate class normally which is obviously not possible if the class is abstract.

    That's why if you specify class as a service too, the class will be also proxied and this entire thing will work.

    Regarding your last remark, you can't eat your cake and have it too. If you want to proxy the class then the class is the target of the proxy.