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.
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.
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.
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.
I would use Unity. Its contained in the enterprise library, and has tons of hands on labs. Super simple.
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.
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.
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);
}
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.
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.
Cheers