Skip to content

Instantly share code, notes, and snippets.

@audinue
Created August 9, 2017 07:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save audinue/5d42d6fd503135e355eeadf4966f1d7e to your computer and use it in GitHub Desktop.
Save audinue/5d42d6fd503135e355eeadf4966f1d7e to your computer and use it in GitHub Desktop.
An automatic dependency injection container.
using System;
using System.Collections.Generic;
using System.Linq;
public sealed class Container
{
private Dictionary<Type, Type> concreteTypes = new Dictionary<Type, Type>();
private Dictionary<Type, object> objects = new Dictionary<Type, object>();
private Type FindConcreteTypeFor(Type type)
{
Type concreteType;
concreteTypes.TryGetValue(type, out concreteType);
if (concreteType != null)
return concreteType;
try
{
concreteType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.First(t => t != type && type.IsAssignableFrom(t));
concreteTypes[type] = concreteType;
return concreteType;
}
catch (Exception)
{
throw new Exception(string.Format("Unable to find concrete type for '{0}'.", type));
}
}
/// <summary>
/// Maps concrete type y to abstract type x.
/// </summary>
public Container Map(Type x, Type y)
{
if (x == null)
throw new ArgumentNullException("x");
if (y == null)
throw new ArgumentNullException("y");
concreteTypes[x] = y;
return this;
}
/// <summary>
/// Maps concrete type Y to abstract type X.
/// </summary>
public Container Map<X, Y>()
{
return Map(typeof(X), typeof(Y));
}
/// <summary>
/// Maps object y to abstract type x.
/// </summary>
public Container Map(Type x, object y)
{
if (x == null)
throw new ArgumentNullException("x");
objects[x] = y;
return this;
}
/// <summary>
/// Maps object y to abstract type X.
/// </summary>
public Container Map<X>(object y)
{
return Map(typeof(X), y);
}
/// <summary>
/// Creates an object of the given type.
/// </summary>
public object Create(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
object @object;
objects.TryGetValue(type, out @object);
if (@object != null)
return @object;
if (type.IsAbstract)
return Create(FindConcreteTypeFor(type));
var constructor = type.GetConstructors().First();
@object = constructor.Invoke(
constructor.GetParameters()
.Select(parameter => Create(parameter.ParameterType))
.ToArray()
);
objects[type] = @object;
return @object;
}
/// <summary>
/// Creates an object of type T.
/// </summary>
public T Create<T>()
{
return (T)Create(typeof(T));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment