Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac: Register classes that are dependant on specific instances of other classes

I'm just learning Autofac and trying to understand how to work out dependencies between services.

Say I have the following classes:

class ClassA {}
class ClassB {}
class ClassC {}

class Classes
{
    public Classes(ClassA classA, ClassB classB, ClassC classC)
    {
        ...
    }
}

and that I want to register the classes so that it mimics the below behavior.

var classA1 = new ClassA("A1");
var classB1 = new ClassB("B1");
var classC1 = new ClassC("C1");
var classes1 = new Classes(classA1, classB1, classC1);

var classA2 = new ClassA("A2");
var classB2 = new ClassB("B2");
var classC2 = new ClassC("C2");
var classes2 = new Classes(classA2, classB2, classC2);

In short, Classes is dependant on specific instances of ClassA, ClassB and ClassC. How do I do that?

like image 724
Andreas Ågren Avatar asked Feb 21 '23 15:02

Andreas Ågren


1 Answers

If you wanted to be able to create multiple unique instances of the Classes class, I would construct my registration using the parameter passing feature of Autofac. My code would look something like

var builder = new ContainerBuilder();
builder.Register((c,p) => new ClassA(p.Named<string>("a")));
builder.Register((c,p) => new ClassB(p.Named<string>("b")));
builder.Register((c,p) => new ClassC(p.Named<string>("c")));
builder.Register((c,p) => new Classes(
    c.Resolve<ClassA>(new NamedParameter("a", p.Named<string>("ClassA"))),
    c.Resolve<ClassB>(new NamedParameter("b", p.Named<string>("ClassB"))),
    c.Resolve<ClassC>(new NamedParameter("c", p.Named<string>("ClassC")))));

var container = builder.Build();
var classes = container.Resolve<Classes>(
    new NamedParameter("ClassA", "AAAA"),
    new NamedParameter("ClassB", "BBBB"),
    new NamedParameter("ClassC", "CCCCC"));

The first three register calls are telling Autofac that when it wants to build an instance of ClassA (or B or C) it must use extract the value from an instance of NamedParameter with a name of "a" (or "b" or "c") and pass that value to the constructor of ClassA. The NamedParameter object will be passes as part of the Resolve call, like Resolve<ClassA>(new NamedParameter("a", "AAAA")).

The final register call is telling Autofac that it must resolve an instance of ClassA, ClassB, and ClassC and pass those instances to the constructor of Classes. To resolve those dependencies, Autofac has to extract values from some instances of NamedParameter that were passed in and pass those into the Resolve in new NamedParameter instances.

Two things to note.

  1. It might be possible to reuse the NamedParameter instances in the Register call for Classes instead of creating new ones. The p parameter of the anonymous function is a IEnumerable, so it might be possible.
  2. This code was tested using the latest version of Autofac (2.6.1).
like image 176
Rich McCollister Avatar answered Apr 26 '23 23:04

Rich McCollister