Reputation:
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.
Upvotes: 6
Views: 2697
Reputation:
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();
}
}
Upvotes: 11