0

When using Autofac I find myself writing a lot of boilerplate code like this:

public class MyClass {
    [...]

    public MyClass(IFoo foo, IBar bar, IBaz baz) {
        _foo = foo;
        _bar = bar;
        _baz = baz;
    }
}

Is there a way of automatically assigning constructor-injected dependencies to their equivalent member variables based on name convention (a la AutoMapper) with Autofac? Or maybe you could use attributes to tell Autofac which properties it should inject, eg.:

[DependencyInjected]
private IFoo _foo;

[DependencyInjected]
private IBar _bar;

[DependencyInjected]
private IBaz _baz;
Jez
  • 27,951
  • 32
  • 136
  • 233

1 Answers1

2

Is there a way of automatically assigning constructor-injected dependencies to their equivalent member variables based on name convention (a la AutoMapper) with Autofac?

No, not unless you build it yourself. Autofac is only compatible with standard OOP practices, which do not include using Reflection to populate private member variables.

When implementing the Dependency Injection pattern in C# there are 3 different ways that dependencies can be injected:

  1. Constructor Injection
  2. Property Injection (also called Setter injection)
  3. Method Injection

There is no accepted pattern for injecting private member variables. In fact, this cannot be done with standard OO principles, in .NET it can only be accomplished using Reflection.

Also, when using the the Dependency Injection pattern, there is no rule that says you must use a DI container such as Autofac. In fact, the use of a DI container is completely optional when applying the DI pattern. For example, when making unit tests it is easy to use the pattern without Autofac - here is an example that uses NUnit and Moq.

[Test]
public void TestDoSomething()
{
    // Arrange
    var foo = new Mock<IFoo>();
    var bar = new Mock<IBar>();
    var baz = new Mock<IBaz>();
    var target = new MyClass(foo.Object, bar.Object, baz.Object);

    // Act
    var result = target.DoSomething();

    // Assert
    Assert.IsNotNull(result);
    // Test other conditions
}

On the other hand, if you add this extra bit of Reflection, you would need access to it in order to populate your MyClass with dependencies.

[Test]
public void TestDoSomething()
{
    // Arrange
    var foo = new Mock<IFoo>();
    var bar = new Mock<IBar>();
    var baz = new Mock<IBaz>();
    var target = new MyClass();

    // Use Reflection to insert the dependencies into the object
    InjectDependencies(target, foo.Object, bar.Object, baz.Object);

    // Act
    var result = target.DoSomething();

    // Assert
    Assert.IsNotNull(result);
    // Test other conditions
}

A big concern here is that the code will compile fine if you completely remove the InjectDependencies(target, foo, bar, baz); line and you will probably end up with a NullReferenceException at runtime somewhere in your class. The purpose of an instance constructor is:

to create and initialize any instance member variables when you use the new expression to create an object of a class.

This guarantees the object is correctly constructed with all of its dependencies. A typical example of the DI pattern with constructor injection:

public class MyClass 
{
    private readonly IFoo _foo;
    private readonly IBar _bar;
    private readonly IBaz _baz;

    public MyClass(IFoo foo, IBar bar, IBaz baz) {
        _foo = foo ?? throw new ArgumentNullException(nameof(foo));
        _bar = bar ?? throw new ArgumentNullException(nameof(bar));
        _baz = baz ?? throw new ArgumentNullException(nameof(baz));
    }
}

The above example uses the readonly keyword and guard clauses in the constructor (which are missing from your example) to guarantee the instance of MyClass cannot be created unless all of its dependencies are supplied. In other words, there is a 0% chance that any of the member variables will ever be null, so you will not have to worry about increasing the complexity of the code by adding null checks to the rest of the class. There is also a 0% chance that any code outside of the constructor can change any of the dependencies, which could cause hard-to-find stability issues with the application.

The bottom line is, you could use Reflection to populate your classes this way if you would like to build your own Autofac extension and write null checks throughout your class, but I wouldn't recommend it because you are taking something that is achieving loose coupling with pure OOP and turning it into a tightly-coupled piece of Reflection code that all of your classes (and anyone who uses them) will depend upon.

You are also removing the possibility of using the handy features of C# that guarantee that the instance will always have all of its dependencies regardless of the context in which it is used (DI container or no DI container) and that they cannot be unwittingly replaced or set to null during runtime.

Workaround

If your primary concern about "boilerplate code" is that you have to type the constructor code yourself, here are a couple of Visual Studio extensions that automate that part:

enter image description here

Unfortunately, neither one of them seems to add the guard clause to the constructor.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Fair point - but how about if you had a method like Autofac.WireUpDependencies() that you always put in the *constructor*? If it threw an exception when the dependency was null it would still ensure they were injected OK. Yes it would add a Nuget dependency or something but presumably you've already got some of those. – Jez Mar 28 '18 at 13:41
  • *how about if you had a method like Autofac.WireUpDependencies() that you always put in the constructor?* - At the end of the day it is the *container* that will need to be accessed in the constructor rather than simply injecting its dependencies. Effectively, you will end up with a [service locator](http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/), which is yet another way to tightly-couple your class to the DI container. It seems like less work until you [consider ongoing maintenance of the project](https://stackoverflow.com/a/38202169). – NightOwl888 Mar 28 '18 at 13:50
  • But you admit that the "memberVariable = argument" code I gave as an example is the kind of boilerplate code that's likely to be repeated in class after class after class? – Jez Mar 28 '18 at 18:49
  • Yes. I would even admit you are right to look for a way to automate it, even though there are really no better ways than using constructor injection. However, many others here with a similar question are asking about how to automate Visual Studio to generate the dependency code in their constructors, which IMO is a more worthy endeavor. [Here](https://marketplace.visualstudio.com/items?itemName=CONWID.DependencyInjectionToolset) and [here](https://marketplace.visualstudio.com/items?itemName=Koshelew.DiConstructorGeneratorExtension) are a couple of VS extensions that do just that. – NightOwl888 Mar 28 '18 at 18:56
  • Is it a more worthy endeavor? If you just had a one-liner "wire up dependencies" then to add a new dependency you just need to add it to the constructor signature and as a member variable but you don't need to add the extra line of wireup. – Jez Mar 29 '18 at 11:40