Coder Perfect

“Friendly” library for Dependency Inject (DI).

Problem

I’m thinking about creating a C# library with multiple different high-level functions. Those high-level functions will, of course, be implemented as much as possible utilising SOLID class design principles. As a result, there will most likely be classes designed for consumers to use on a regular basis, as well as “support classes” that are dependent on the more prevalent “end user” classes.

What is the best method to create the library in such a way that it is:

My current thought is to give a set of non-DI Factory classes that contain the connection to those few factories, as well as a few “DI registration modules” for the common DI libraries (e.g., a StructureMap registry, a Ninject module).

Thoughts?

Asked by Pete

Solution #1

This is actually quite straightforward if you realise that DI is all about patterns and ideas rather than technology.

Follow these broad concepts while designing an API that is DI Container agnostic:

Not an implementation, but a program to an interface

This principle is a statement (from memory) from Design Patterns, but it should always be your primary objective. DI is merely a tool for achieving that goal.

Put the Hollywood Rule to Work

In DI terminology, the Hollywood Principle states: Don’t call the DI Container; it will call you.

By invoking a container from within your code, you should never ask for a dependency explicitly. Using Constructor Injection, you can ask for it implicitly.

Use Constructor Injection

When you need a dependency, use the constructor to request it statically:

public class Service : IService
{
    private readonly ISomeDependency dep;

    public Service(ISomeDependency dep)
    {
        if (dep == null)
        {
            throw new ArgumentNullException("dep");
        }

        this.dep = dep;
    }

    public ISomeDependency Dependency
    {
        get { return this.dep; }
    }
}

Take note of how the Service class ensures invariants. Because of the Guard Clause and the readonly keyword, the dependence is assured to be available once an instance is created.

If you require a one-time object, use Abstract Factory.

Constructor Injection dependencies tend to be long-lived, but there are situations when you require a short-lived object or to construct the reliance based on a value known only at run-time.

For further details, see here.

Only compose at the last possible moment.

Until the very end, keep objects disconnected. Normally, you may wait until the application’s entry point to wire everything up. The Composition Root is what it’s called.

More details here:

Use a Facade to simplify things.

You can always offer a few Facade classes that encapsulate typical dependency combinations if you think the resulting API becomes too complex for beginner users.

You might give Fluent Builders to provide a configurable Facade with a high degree of discoverability. Something along these lines:

public class MyFacade
{
    private IMyDependency dep;

    public MyFacade()
    {
        this.dep = new DefaultDependency();
    }

    public MyFacade WithDependency(IMyDependency dependency)
    {
        this.dep = dependency;
        return this;
    }

    public Foo CreateFoo()
    {
        return new Foo(this.dep);
    }
}

This would enable a user to define a default Foo by simply writing it down.

var foo = new MyFacade().CreateFoo();

It would, however, be quite obvious that you may supply a custom dependence, and you could write code to do so.

var foo = new MyFacade().WithDependency(new CustomDependency()).CreateFoo();

If you envisage the MyFacade class encapsulating a variety of dependencies, it should be evident how it would give appropriate defaults while yet allowing extension to be discovered.

FWIW, I built on the principles in this answer and produced a larger blog article about DI-Friendly Libraries, as well as a companion piece about DI-Friendly Frameworks, long after I provided this answer.

Answered by Mark Seemann

Solution #2

Even though the terms “dependency injection” and “IoC container” are frequently used interchangeably, they have nothing to do with each other. It basically means that instead of writing your code like this, you should write it like this:

public class Service
{
    public Service()
    {
    }

    public void DoSomething()
    {
        SqlConnection connection = new SqlConnection("some connection string");
        WindowsIdentity identity = WindowsIdentity.GetCurrent();
        // Do something with connection and identity variables
    }
}

This is how you put it:

public class Service
{
    public Service(IDbConnection connection, IIdentity identity)
    {
        this.Connection = connection;
        this.Identity = identity;
    }

    public void DoSomething()
    {
        // Do something with Connection and Identity properties
    }

    protected IDbConnection Connection { get; private set; }
    protected IIdentity Identity { get; private set; }
}

That is, when you write code, you perform two things:

None of this requires the use of a DI library, and it doesn’t make the code any more difficult to create if one isn’t available.

If you want to see an illustration of this, look no further than the.NET Framework:

etc., etc., etc., etc., etc., etc., etc., In.NET, you’ll find DI all over the place; it’s just that it’s usually done so flawlessly that you don’t even notice it’s DI.

If you want to make your DI-enabled library as user-friendly as possible, the best recommendation is to provide your own default IoC implementation utilizing a lightweight container. Because IContainer is part of the.NET Framework, it’s an excellent choice.

Answered by Aaronaught

Solution #3

EDIT 2015: As time has gone, I’ve come to see that this was all a horrible mistake. IoC containers are awful, and DI is a bad approach to handle side effects. All of the responses (as well as the question itself) should be avoided. Simply be mindful of side effects and segregate them from pure code, and the rest will either fall into place or be redundant complication.

Original answer follows:

While developing SolrNet, I had to make the same decision. I started with the intention of making the library DI-friendly and container-agnostic, but as I added more internal components, the internal factories got unmanageable, and the library grew rigid.

I ended up developing my own very simple embedded IoC container, with a Windsor facility and a Ninject module thrown in for good measure. It’s just a matter of properly wiring the components to combine the library with other containers, so I could easily integrate it with Autofac, Unity, StructureMap, or anything.

The disadvantage is that I no longer have the ability to simply restart the service. To make the embedded container easier to create, I also took a dependent on CommonServiceLocator, which I might have avoided (I might refactor it away in the future).

This blog post has more details.

Something similar appears to be used by MassTransit. It contains an IObjectBuilder interface that is essentially CommonServiceLocator’s IServiceLocator with a few more methods, which it implements for each container, such as NinjectObjectBuilder, and a regular module/facility, such as MassTransitModule. Then it uses IObjectBuilder to create the objects it need. Of course, this is a valid solution, but I don’t like it because it involves a lot of passing the container around and utilizing it as a service locator.

MonoRail also has its own container, which implements the IServiceProvider interface. Through an interface that provides well-known services, this container is used across this framework. It contains a built-in service provider finder to get the concrete container. Windsor is the chosen service provider since the Windsor facility points this service provider locator to Windsor.

In the end, there is no such thing as a perfect answer. This issue, like any other design decision, necessitates a balance of flexibility, maintainability, and ease.

Answered by Mauricio Scheffer

Solution #4

To reduce dependency on the container as much as feasible, I would create my library in a DI container independent manner. This allows you to replace one DI container with another if necessary.

Then, through your interface, expose the layer above the DI logic to the library’s users, allowing them to utilize whatever framework you choose. This way, customers can continue to use the DI capabilities you revealed while also being free to use any alternative framework for their own needs.

Allowing library users to bring in their own DI framework sounds a little odd to me, as it significantly increases the amount of upkeep. This thus becomes more of a plugin environment rather than a DI environment.

Answered by Igor Zevaka

Post is based on https://stackoverflow.com/questions/2045904/dependency-inject-di-friendly-library