views:

1202

answers:

10

What's the simplest IOC container for C#? Is simple to learn and get productive with for a small app. In my case a winforms app which I want to abstract the data layer for later potential migration to a web-service for the data layer.

+5  A: 

I suggest that you have a look at Ninject. It's easy to learn, and a light weight IoC container.

This documentation is a good starting point, though I don't think it's all up to date.

There are several good options though. Check out e.g. this question for a (non .net specific) discussion on different containers.

stiank81
Would it be good as a not to complex way to help me keep my data layer abstracted for the future?
Greg
Most IoC containers would be good to achieve that, but Ninject is one of the really agile containers that keeps things simple for you.
stiank81
+8  A: 

StructureMap is very easy to get working and works very well and the site has a great set of documentation to explain why you would use IoC/DI etc.

Chris W
Any comments re how it would compare to Ninject re simple/quick rampup?
Greg
I've not tried Ninject for a comparison. I'm looking at Windsor at the moment which seems more advanced overall but getting running with it was still relatively easy.
Chris W
+25  A: 

Most of them are actually pretty simple to learn, so I think that asking for the simplest container is not the best selection criterion.

As an example, one of the most advanced DI Containers is Windsor, but getting started with it is as simple as:

var container = new WindsorContainer();
container.AddComponent<IMyInterface, MyImp>();

var i = container.Resolve<IMyInterface>();

I'm not particularly suggesting Windsor over any other container, but my main point is that it shouldn't really matter.

What matters is that you understand DI principles and structure your code in a DI-friendly manner and that you select a container that will not constrain you as you learn more advanced concepts. Selecting the simplest possible container isn't likely to satisfy that.

Mark Seemann
+4  A: 

I would use Unity. Its contained in the enterprise library, and has tons of hands on labs. Super simple.

http://msdn.microsoft.com/en-us/library/dd203104.aspx

Unity Hands on labs

Nix
Wow, there seem to be lots. No obvious "most popular" then in the general "simple" category I'm describing?
Greg
Like Mark said, they are all quiet simple and do relatively the same thing. Enterprise library is nice because a it comes with EL so you have it in your tool box, they have hands on labs, and people use it in production code.
Nix
+2  A: 

I find that TinyIoC is very simple and easy to use.

Here is an example that equals Marks example.

var container = TinyIoCContainer.Current;
container.AutoRegister();
var i = container.Resolve<IMyInterface>();

But I agree with Mark in his point that it shouldn't really matter which DI container you use.

slamidtfyn
A: 

SimpleServiceLocator is (as the name implies) the simplest (shameless plug). Quote from the site:

The Simple Service Locator is an easy-to-use Inversion of Control library that is a complete implementation of the Common Service Locator interface. It solely supports code-based configuration and is an ideal starting point for developers unfamiliar with larger IoC / DI libraries

Here is an example that equals Marks example.

// Configure
var container = new SimpleServiceLocator();  
container.Register<IMyInterface>(() => new MyImp());

Microsoft.Practices.ServiceLocation
    .ServiceLocator.SetLocatorProvider(() => container);

// Usage
var i = ServiceLocator.Current.GetInstance<IMyInterface>();

Note that the Simple Service Locator uses Func<T> delegates to register types. This has proven itself to be a very flexible and easy way of configuring the container.

Steven
+4  A: 

This one:

public class Container
{
    protected readonly Dictionary<string, Func<object>> services = new Dictionary<string, Func<object>>();
    protected readonly Dictionary<Type, string> serviceNames = new Dictionary<Type, string>();

    public DependencyManager Register<S, C>() where C : S
    {
        return Register<S, C>(Guid.NewGuid().ToString());
    }

    public DependencyManager Register<S, C>(string name) where C : S
    {
        if (!serviceNames.ContainsKey(typeof(S)))
        {
            serviceNames[typeof(S)] = name;
        }
        return new DependencyManager(this, name, typeof(C));
    }

    public T Resolve<T>(string name) where T : class
    {
        return (T)services[name]();
    }

    public T Resolve<T>() where T : class
    {
        return Resolve<T>(serviceNames[typeof(T)]);
    }

    public class DependencyManager
    {
        private readonly Container container;
        private readonly Dictionary<string, Func<object>> args;
        private readonly string name;

        internal DependencyManager(Container container, string name, Type type)
        {
            this.container = container;
            this.name = name;

            ConstructorInfo c = type.GetConstructors().First();
            args = c.GetParameters()
                .ToDictionary<ParameterInfo, string, Func<object>>(
                x => x.Name,
                x => (() => container.services[container.serviceNames[x.ParameterType]]())
                );

            container.services[name] = () => c.Invoke(args.Values.Select(x => x()).ToArray());
        }

        public DependencyManager AsSingleton()
        {
            object value = null;
            Func<object> service = container.services[name];
            container.services[name] = () => value ?? (value = service());
            return this;
        }

        public DependencyManager WithDependency(string parameter, string component)
        {
            args[parameter] = () => container.services[component]();
            return this;
        }

        public DependencyManager WithValue(string parameter, object value)
        {
            args[parameter] = () => value;
            return this;
        }
    }
}

Usage:

[TestMethod]
public void NamedRegistration()
{
    Container c = new Container();
    c.Register<IMathNode, Zero>("zero");
    IMathNode m = c.Resolve<IMathNode>("zero");
    Assert.AreEqual(0, m.Calculate());
}

[TestMethod]
public void AnonymousRegistration()
{
    Container c = new Container();
    c.Register<IMathNode, Zero>();
    IMathNode m = c.Resolve<IMathNode>();
    Assert.AreEqual(0, m.Calculate());
}

[TestMethod]
public void AnonymousSubDependency()
{
    Container c = new Container();
    c.Register<IMathNode, Zero>();
    c.Register<IFormatter, MathFormatter>();
    IFormatter m = c.Resolve<IFormatter>();
    Assert.AreEqual("$0.00", m.Format("C2"));
}

[TestMethod]
public void WithValue()
{
    Container c = new Container();
    c.Register<IMathNode, Number>("five").WithValue("number", 5);
    int i = c.Resolve<IMathNode>("five").Calculate();
    Assert.AreEqual(5, i);
}

[TestMethod]
public void NamedSubDependency()
{
    Container c = new Container();
    c.Register<IMathNode, Number>("five").WithValue("number", 5);
    c.Register<IMathNode, Number>("six").WithValue("number", 6);
    c.Register<IMathNode, Add>("add").WithDependency("m1", "five").WithDependency("m2", "six");
    int i = c.Resolve<IMathNode>("add").Calculate();
    Assert.AreEqual(11, i);
}
Rob Fonseca-Ensor
A: 

Managed Extensibility Framework is part of .NET 4 scoring +1 in simplicty for not having to add an external dependency to your project. (There is also a version for older versions of the framework.) It can do a lot more than the average IoC container, but is quite simple to use:

public static class IocContainer {

  static CompositionContainer container;

  public static void Compose() {
    // All .DLL files in the bin folder.
    var directoryCatalog = new DirectoryCatalog(".");
    // The .EXE file for this application.
    var assemblyCatalog = new AssemblyCatalog(Assembly.GetEntryAssembly());
    // Aggregate .DLL files and .EXE file.
    var aggregateCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog);
   container = new CompositionContainer(aggregateCatalog);
  }

  public static void AddInstance<T>(T instance) {
    if (s_container == null)
        throw new InvalidOperationException("Compose container before using it.");
    container.ComposeExportedValue(instance);
  }

  public static T Resolve<T>() {
    if (container == null)
      throw new InvalidOperationException("Compose container before using it.");
    return container.GetExportedValue<T>();
  }

}

Declaring imports and exports using attributes:

[Export(typeof(ILogger)]
public class Logger : ILogger { ... }

[Export(typeof(IMyService))]
public class MyService : IMyService {

  [ImportingConstructor]
  public MyService(ILogger logger) { ... }

}

Resolving an instance where all the magic happens:

var myService = IocContainer.Resolve<IMyService>();

MEF will create an instance of Logger and then an instance of MyService providing the Logger instance as an argument to the constructor.

Martin Liversage
+2  A: 

Hi,

Munq is one of the simplest & very faster IOC container. Check out this article Introduction to Munq IOC Container for ASP.NET for comparison. Its the fastest one.

Image from the article.

alt text Cheers

Ramesh Vel
container performance is largely irrelevant, they're all fast enough for 99% of applications.
Mauricio Scheffer
A: 

Autofac is very easy to setup and use.

jgauffin