Skip to content
On this page

Auto Wiring

The best way to use an IoC container is to allow "Auto Wiring" to do most of the work for you. IoC Containers like Lamar are an infrastructure concern, and as such, should be isolated from as much of your code as possible. Before examining Auto Wiring in depth, let's look at a common anti pattern of IoC usage:

cs
// This is the wrong way to use an IoC container.  Do NOT invoke the container from
// the constructor function.  This tightly couples the ShippingScreenPresenter to
// the IoC container in a harmful way.  This class cannot be used in either
// production or testing without a valid IoC configuration.  Plus, you're writing more
// code
public ShippingScreenPresenter(IContainer container)
{
    // It's even worse if you use a static facade to retrieve
    // a service locator!
    _service = container.GetInstance<IShippingService>();
    _repository = container.GetInstance<IRepository>();
}

snippet source | anchor

Instead of binding ShippingScreenPresenter so tightly to Lamar and having to explicitly fetch its dependencies, let's switch it to using Lamar a little more idiomatically and just exposing a constructor function with the necessary dependencies as arguments:

cs
// This is the way to write a Constructor Function with an IoC tool
// Let the IoC container "inject" services from outside, and keep
// ShippingScreenPresenter ignorant of the IoC infrastructure
public ShippingScreenPresenter(IShippingService service, IRepository repository)
{
    _service = service;
    _repository = repository;
}

snippet source | anchor

As long as a Lamar Container knows how to resolve the IRepository and IShippingService interfaces, Lamar can build ShippingScreenPresenter by using "auto-wiring." All this means is that instead of forcing you to explicitly configure all the dependencies for ShippingScreenPresenter, Lamar can infer from the public constructor function what dependencies ShippingScreenPresenter needs and uses the defaults of both to build it out.

Looking at the build plan for ShippingScreenPresenter:

cs
[Fact]
public void ShowBuildPlan()
{
    var container = new Container(_ =>
    {
        _.For<IShippingService>().Use<InternalShippingService>();
        _.For<IRepository>().Use<SimpleRepository>();
    });

    // Just proving that we can build ShippingScreenPresenter;)
    container.GetInstance<ShippingScreenPresenter>().ShouldNotBeNull();

    var buildPlan = container.Model.For<ShippingScreenPresenter>().Default.DescribeBuildPlan();

    // _output is the xUnit ITestOutputHelper here
    _output.WriteLine(buildPlan);
}

snippet source | anchor