2

Let's say I have the following hierarchy.

class PersonWithJacket
{
    public PersonWithJacket(Jacket jacket)
    {
    }
}

class Jacket
{
    public Jacket(string brand)
    {
    }
}

I register these classes in my Autofac container

        containerBuilder.RegisterType<PersonWithJacket>();
        containerBuilder.RegisterType<Jacket>();

At runtime I want to resolve a PersonWithJacket object and I want to define the string brand constructor parameter of the nested Jacket class. My first approach was to use the NamedParameter like so:

        var personWithJacket = container.Resolve<PersonWithJacket>(new NamedParameter("brand", "TheBrand"));

I read that as "resolve the a PersonWithJacket object and if you encounter a constructor parameter called 'brand', use the value 'TheBrand'" but the string parameter cannot be resolved.

Is there a way to define, at runtime, the value of a constructor parameter of a nested object?

Tobias
  • 4,999
  • 7
  • 34
  • 40
  • Can you be a bit more specific with what you are trying to accomplish? Are you trying to pass in a `Jacket` to the `PersonWithJacket` ctor? Is `PersonWithJacket` supposed to inherit `Jacket`? – Mohammed Hossain Sep 09 '14 at 00:04
  • I basically want to get two different `PersonWithJacket` objects each with a different `Jacket`'s brand name. Does that make it clearer? – Tobias Sep 09 '14 at 00:13
  • Oh, I see. I assume that these name brand `Jacket`s are registered with Autofac as well? – Mohammed Hossain Sep 09 '14 at 00:15
  • The Jacket is but it's names are not because they are only known at runtime. – Tobias Sep 09 '14 at 00:16
  • Ah, I think I got it. Let me write it up. – Mohammed Hossain Sep 09 '14 at 00:28
  • Bah, doing it in a nice and clean way is a lot harder than I thought it would be. For now, you can simply resolve the `Jacket` first, and then pass that value into `Resolve(jacket)`; – Mohammed Hossain Sep 09 '14 at 00:39

2 Answers2

1

Oh, never mind. It's not that bad with ResolvedParameters.

        using (var scope = container.BeginLifetimeScope()) {
            var someDynamicString = "Brand B";

            var personDude = scope.Resolve<PersonWithJacket>(new ResolvedParameter(
                (pi, ctx) => pi.ParameterType == typeof(Jacket),
                (pi, ctx) => ctx.Resolve<Jacket>(new NamedParameter("name", someDynamicString))));
        }
Mohammed Hossain
  • 1,319
  • 10
  • 19
  • Thanks for your answer but this is not flexible enough. I solved it with `MultitenantContainers`. – Tobias Sep 11 '14 at 01:35
1

The way to do it seems to be by using a container hierarchy. I create a base container where I register all the common types and instances and then create child containers that register the parts that vary.

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<PersonWithJacket>();

var childContainer1 = new MultitenantContainer(new NullTenantIdStrategy(), containerBuilder.Build());
childContainer1.ConfigureTenant(null, builder => builder.Register(context => new Jacket("Hugo Boss")));

var childContainer2 = new MultitenantContainer(new NullTenantIdStrategy(), containerBuilder.Build());
childContainer2.ConfigureTenant(null, builder => builder.Register(context => new Jacket("H&M")));

var personWithHugoBossJacket = childContainer1.Resolve<PersonWithJacket>();
var personWithHandMJacket = childContainer2.Resolve<PersonWithJacket>();
Tobias
  • 4,999
  • 7
  • 34
  • 40