Search code examples
c#unity-containerioc-containerparams-keyword

Is it possible to specify variable-length constructor arguments when registering in Unity?


I have an interface, IFoo, and three concrete classes: FooA : IFoo, FooB : IFoo, and MultiFoo : IFoo.

The constructor for MultiFoo looks like this:

public MultiFoo(params IFoo[] foos) { ... }

Can I specify particular resolution overrides when registering MultiFoo in Unity? I would like to be able to do something like this:

container.RegisterType<IFoo, FooA>("Foo A");
container.RegisterType<IFoo, FooB>("Foo B");

container.RegisterType<IFoo, MultiFoo>(new ContainerControlledLifetime(),
    new ResolvedOverride<IFoo>("Foo A"),
    new ResolvedOverride<IFoo>("Foo B")
);

which would then pass a resolved FooA and a resolved FooB to the constructor at resolve-time:

new MultiFoo(new FooA(), new FooB())

Solution

  • params are compiler syntactic sugaring, you're really passing an array as a single parameter. To match that you'd configure the container like this:

    container.RegisterType<IFoo, MultiFoo>(new ContainerControlledLifetimeManager(),
        new InjectionConstructor(new ResolvedArrayParameter<IFoo>(new ResolvedParameter<IFoo>("Foo A"), new ResolvedParameter<IFoo>("Foo B"))));
    

    Resolver overrides are used at Resolve time, not at container setup time. The equivalent using resolve overrides would look like this:

    container.RegisterType<IFoo, MultiFoo>(new ContainerControlledLifetimeManager());
    
    var foo = container.Resolve<IFoo>(
        new ParameterOverride(
            "foos", 
            new ResolvedArrayParameter<IFoo>(new ResolvedParameter<IFoo>("Foo A"), new ResolvedParameter<IFoo>("Foo B"))));