Manish Kumar
Manish Kumar

Reputation: 113

Autofac: Resolving contructor parameters based on single dependency

I have a scenario which I want autofac to resolve:

Here are my classes, I would have a factory method to take NetworkCredentials and return TopLevel object, this should internally resolve the InnerType1 and InnerType2 with the NetwokCredentials

 public class TopLevel
{
    public TopLevel(InnerType1 type1, InnerType2 type2)
    {            
    }
}

public class InnerType1
{
    public InnerType1(NetworkCredential credential)
    {
    }
}
public class InnerType2
{
    public InnerType2(NetworkCredential credential)
    {
    }
}

Registration code > would something like this work ?

builder.Register<Func<NetworkCredential, TopLevel>>(c =>
        {
            var context = c.Resolve<IComponentContext>();
            return (cred) => context.Resolve<TopLevel>(new TypedParameter(typeof(NetworkCredential), cred));
        });

The crude approach could be to do resolve each contructor argument one by one inside resolution of TopLevel

Upvotes: 1

Views: 119

Answers (2)

Jim Bolla
Jim Bolla

Reputation: 8295

Similar to Peter's answer, but slightly different flavor:

builder.Register<Func<NetworkCredential, TopLevel>>(c =>
{
    var resolveInnerType1 = c.Resolve<Func<NetworkCredential, InnerType1>>();
    var resolveInnerType2 = c.Resolve<Func<NetworkCredential, InnerType2>>();
    var resolveTopLevel = c.Resolve<Func<InnerType1, InnerType2, TopLevel>>();

    return (cred) => {
            var i1 = resolveInnerType1(cred);
            var i2 = resolveInnerType2(cred);
            return resolveTopLevel(i1, i2);
        };
});

Upvotes: 0

Peter Lillevold
Peter Lillevold

Reputation: 33930

No, that will not work since you are now instructing Autofac to provide a parameter value of type NetworkCredential to the TopLevel constructor which clearly requires two parameters of totally different types.

You will have to resolve InnerType1 and InnerType2 instances first and provide these to the TopLevel resolve. Something like this:

builder.Register<Func<NetworkCredential, TopLevel>>(c =>
    {
        var context = c.Resolve<IComponentContext>();
        return (cred) => {
            var i1 = context.Resolve<InnerType1>(TypedParameter.From(cred));
            var i2 = context.Resolve<InnerType2>(TypedParameter.From(cred));
            return context.Resolve<TopLevel>(TypedParameter.From(i1), TypedParameter.From(i2));
            };
    });

Note: I'm not seeing the whole picture of your system here, but if you feel that this is crude, perhaps you should look at revising your class hierarchy. IMO there's a faint smell of "too complex" in your code here, you require two different classes to be configured with the same data which makes me want to de-duplicate :)

Upvotes: 1

Related Questions