Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a small IoC Container in C#

I decided to create a very small IoC container in C# for a MonoGame project. The reason i decided to create one myself is to improve the performance and use less libraries that i don't control. Since IoC is something so simple, i don't think a library should handle it.

I started a naive implementation:

var container = new Container();
container.Register("service-alias",
    container => new ServiceClass(container.Resolve("other.dep"));

container.Resolve("service-alias").MethodOnServiceClass()

But I have no idea how to do this in C#'s type system. A Dictionary <string, Func<Container>>? How do I type the return of the resolve method?

like image 378
vinnylinux Avatar asked Sep 14 '15 15:09

vinnylinux


People also ask

Should I use IoC container?

An IOC container allows the declaration of dependencies behind a proxy object. When this happens, we can more easily control whether those dependencies are Transient or Singleton. Having this sort of control lets us open up design opportunities and better UI architecture in our app.

What is IoC container?

IoC container is a framework for implementing automated dependency injection. It contains object creation for the longer ways to use and injects dependencies within the class.

What is the difference between Spring container and IoC container?

An IoC container is a common characteristic of frameworks that implement IoC. In the Spring framework, the interface ApplicationContext represents the IoC container. The Spring container is responsible for instantiating, configuring and assembling objects known as beans, as well as managing their life cycles.


2 Answers

Here is an example implementation with 21 lines of code. But please don't be tempted to simplify development by implementing some dictionary that holds the registrations (other than doing so for educational purposes). There are many downsides to hand rolling your own DI library. As explained here, you are much better of by applying Pure DI (which means: DI without DI library) and switching from Pure DI to a DI library later on, in case -and ONLY in case- your Composition Root becomes hard to maintain without.

like image 186
Steven Avatar answered Sep 28 '22 09:09

Steven


I really recommend a pragmatic approach here.

1) Design an abstraction for "your dream IoC container", with only the bare minimum that you need. Something like this:

public interface IContainer 
{
    void RegisterType<TSource, TDestination>();
    void RegisterType<TSource>(Func<TSource, TDestination> generator);
    T Resolve<T>(); 
}

2) Create an implementation of your abstraction that simply delegates all the functionality to an existing component. I recommend Autofac but there's plenty of fish in the sea.

3) Develop your application using your "wrapper IoC".

4) If at some point you find that the external IoC component has performance issues (or any other type of issues), write another implementation of your IoC abstraction that uses another external component, your own code, or a combination of both. Even if your application is in an advanced state, you just have to change the small piece of code that instantiates the IoC wrapper (perhaps just one line of code).

Advantages of this approach:

  1. You use a mature and well-tested IoC container (if you choose wisely) while hiding its complexity behind a small interface. This helps improve code readability.
  2. You don't fall in the premature optimization trap.
  3. You can entirely switch from one IoC container to another one with very little impact in your existing code (if your abstraction is well designed). This wipes out (or at least minimizes) the "using libraries that I don't control" concern.

Of course, you will have to make the abstraction grow as you need more advanced functionality. But you should always start with a simple abstraction.

At my work place we are using a more elaborate version of this approach and it's working nicely.

like image 43
Konamiman Avatar answered Sep 28 '22 09:09

Konamiman