Pergunta

I'm trying to create a typed factory as per Windsor's example. This is my factory interface:

public interface ICustomJsonResultFactory
{
    JsonResult Create();
}

In my global.asax, I'm setting up the Windsor container by first adding the following two facilities:

.AddFacility<FactorySupportFacility>()
.AddFacility<TypedFactoryFacility>();

After that's done, I register my components:

Component.For<JsonResult>()
    .ImplementedBy<CustomJsonResult>()
    .LifestyleTransient(),
Component.For<ICustomJsonResultFactory>()
    .AsFactory())

One of my controllers has a ICustomJsonResultFactory property. When I try resolving the controller, I get the following in my logs:

Castle.Core.DependencyResolution: DEBUG 8 - 
    Client:     DefaultTypedFactoryComponentSelector / ITypedFactoryComponentSelector
    Model:      Dependency 'getMethodsResolveByName' type 'System.Boolean'
    Dependency: True
Castle.Core.DependencyResolution: DEBUG 8 - 
    Client:     DefaultTypedFactoryComponentSelector / ITypedFactoryComponentSelector
    Model:      Dependency 'fallbackToResolveByTypeIfNameNotFound' type 'System.Boolean'
    Dependency: False
Castle.Core.DependencyResolution: DEBUG 8 - 
    Client:     TypedFactoryInterceptor
    Model:      Dependency 'kernel' type 'Castle.MicroKernel.IKernelInternal'
    Dependency: Castle.MicroKernel.DefaultKernel
Castle.Core.DependencyResolution: DEBUG 8 - 
    Client:     TypedFactoryInterceptor
    Model:      Dependency 'componentSelector' type 'Castle.Facilities.TypedFactory.ITypedFactoryComponentSelector'
    Dependency: Castle.Facilities.TypedFactory.DefaultTypedFactoryComponentSelector
A first chance exception of type 'System.ArgumentException' occurred in Castle.Windsor.dll
A first chance exception of type 'System.ArgumentException' occurred in Castle.Windsor.dll
A first chance exception of type 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' occurred in Castle.Windsor.dll

I think this part is important, so I'm pointing it out:

Castle.Windsor Warning: 0 : Exception when resolving optional dependency Dependency 'JsonResultFactory' type 'CompanyName.Web.Mvc.ICustomJsonResultFactory' on component CompanyName.Web.OrderProcessing.Controllers.PickTicketController., Castle.MicroKernel.ComponentActivator.ComponentActivatorException: ComponentActivator: could not proxy CompanyName.Web.Mvc.ICustomJsonResultFactory ---> System.ArgumentException: Component CompanyName.Web.Mvc.ICustomJsonResultFactory is not a typed factory. TypedFactoryInterceptor only works with typed factories.

   at Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.SetInterceptedComponentModel(ComponentModel target)
at Castle.Windsor.Proxy.AbstractProxyFactory.SetOnBehalfAware(IOnBehalfAware onBehalfAware, ComponentModel target)
at Castle.Windsor.Proxy.AbstractProxyFactory.ObtainInterceptors(IKernel kernel, ComponentModel model, CreationContext context)
at Castle.Windsor.Proxy.DefaultProxyFactory.Create(IKernel kernel, Object target, ComponentModel model, CreationContext context, Object[] constructorArguments)
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
--- End of inner exception stack trace ---
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.Instantiate(CreationContext context)
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden)
at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally)
at Castle.MicroKernel.Lifestyle.SingletonLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
at Castle.MicroKernel.Handlers.ExtendedHandler.InvokeResolvePipeline(Int32 extensionIndex, ResolveInvocation invocation)
at Castle.MicroKernel.Handlers.ExtendedHandler.<>c__DisplayClass6.<InvokeResolvePipeline>b__5()
at Castle.MicroKernel.Handlers.ResolveInvocation.Proceed()
at Castle.MicroKernel.Handlers.ComponentLifecycleExtension.Intercept(ResolveInvocation invocation)
at Castle.MicroKernel.Handlers.ExtendedHandler.InvokeResolvePipeline(Int32 extensionIndex, ResolveInvocation invocation)
at Castle.MicroKernel.Handlers.ExtendedHandler.Resolve(CreationContext context, Boolean instanceRequired)
at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernelByType(CreationContext context, ComponentModel model, DependencyModel dependency)
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveFromKernel(CreationContext context, ComponentModel model, DependencyModel dependency)
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.ResolveCore(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
at Castle.MicroKernel.Resolvers.DefaultDependencyResolver.Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.ObtainPropertyValue(CreationContext context, PropertySet property, IDependencyResolver resolver)

I've tried adding the Release method to the controller per Windsor's example. I also tried having the factory's Create return an interface instead of a JsonResult. I've tried going through the Windsor source using ILSpy to no avail.

What am I doing wrong? I think I'm following the example pretty closely... is the problem in my code, or in Windsor?

I'm using version 3.2.0 of the various Castle libraries with .Net 4.5.

Foi útil?

Solução

Turns out I was installing the facility after registering my factory component. I thought it was before all my components, but I was mistaken. You have to install the facility first. I wrongly expected an exception in AsFactory() if the facility wasn't yet installed.

Here is a complete program that reproduces the issue.

public interface IFooFactory {   IFoo Create();   }
public interface IFoo        {   void DoFoo();    }

public class Foo : IFoo
{
    public void DoFoo()
    {
        Console.WriteLine("I pity the foo");
    }
}

public class Bar
{
    public IFooFactory MyFooFactory { get; set; }

    public void DoBar()
    {
        var foo = MyFooFactory.Create();
        foo.DoFoo();
    }

    static void Main(string[] args)
    {
        var container = new WindsorContainer();
        container.Register(
            Component.For<Bar>().ImplementedBy<Bar>().LifestyleTransient(),
            Component.For<IFoo>().ImplementedBy<Foo>().LifestyleTransient(),
            Component.For<IFooFactory>().AsFactory());
        container.AddFacility<TypedFactoryFacility>();
        var bar = container.Resolve<Bar>();
        bar.DoBar();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top