Search code examples
c#castle-windsor

How to mix DynamicParameters and DependsOn


I guess I'm missing something, or I'm in someway doing something stupid, but I can't fathom it out. Assume the following two classes:

public class A
{
    public A(string a, string b)
    {
    }
}

public class B
{
    public B(A boris2)
    {
    }
}

And this main method:

private static void Main(string[] args)
{
    var container = new WindsorContainer();
    container.Register(
        Component.For<A>().LifeStyle.Transient.ImplementedBy<A>().Named("Boris2")
        //.DynamicParameters((k,d)=>{
        //  d["b"] = "jkl";
        //})
        .DependsOn(new { a = "ghi", b="jkl" })
        );

    container.Register(
        Component.For<B>().LifeStyle.Transient.ImplementedBy<B>()
        .DependsOn(Dependency.OnComponent("boris2", "Boris2"))
        );

    var b = container.Resolve<B>();
    Console.WriteLine("Okay");
    Console.ReadKey();
}

If I run this method as shown above, it prints Okay, I press return, and it exits. All is fine. However, As shown in the commented out code, I want the b parameter to be dynamicly computed (eventually it will be, but I just wanted to get to the nub of the issue)

So, if I make my first call to Register look like this instead:

    container.Register(
        Component.For<A>().LifeStyle.Transient.ImplementedBy<A>().Named("Boris2")
        .DynamicParameters((k, d) =>
        {
            d["b"] = "jkl";
        })
        .DependsOn(new { a = "ghi" })
        );

Which I thought would be roughly equivalent, I now get an exception:

Castle.MicroKernel.Handlers.HandlerException was unhandled
  HelpLink=groups.google.com/group/castle-project-users
  HResult=-2146233088
  Message=Can't create component 'PlayAreaCS_Con.B' as it has dependencies to be satisfied.

'PlayAreaCS_Con.B' is waiting for the following dependencies:
- Component 'Boris2' (via override) which was registered but is also waiting for dependencies.

'Boris2' is waiting for the following dependencies:
- Parameter 'b' which was not provided. Did you forget to set the dependency?

  Source=Castle.Windsor
  StackTrace:
       at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency()
       at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
       at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
       at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
       at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
       at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
       at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments)
       at Castle.Windsor.WindsorContainer.Resolve[T]()
       at PlayAreaCS_Con.Program.Main(String[] args) in c:\Dev\PlayAreaCS_Con\PlayAreaCS_Con\Program.cs:line 49
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

I even tried moving both parameters into DynamicParameters and removing DependsOn, thinking it may be some issue with mixing the two together, but it still errors. From what I can work out, it's not invoking my lambda at all.

What am I doing wrong?

Edit

If I comment out:

.DependsOn(Dependency.OnComponent("boris2", "Boris2"))

From my second Register call, then it works. But I do need to have several identical components registered in the container, only distinguished by name. (I've removed the other registration from the first Register call, since it doesn't seem to be relevant)


Solution

  • I don't know what to say, other than: works on my machine (with Windsor 3.2), with the original (first) code, where I just uncommented the commented out code.