Created
May 19, 2010 15:19
-
-
Save jamesfoster/406407 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ContainerException : Exception { | |
public ContainerException(string s) : base(s) {} | |
} | |
public interface IContainer { | |
void Add<T>(); | |
void Add<Interface, Component>() | |
void Add<T>(Func<T> resolver) | |
T Resolve<T>() | |
object Resolve(Type type) | |
void Decorate<Interface, Component>() | |
} | |
public interface IActivator { | |
object Activate() | |
} | |
public class LazyActivator : IActivator { | |
private Func<object> _activator; | |
public LazyActivator(Func<object> activator) { | |
_activator = activator; | |
} | |
public object Activate() { | |
return _activator(); | |
} | |
} | |
public class SimpleContainer : IContainer { | |
private Func<Type, object> _missingHandler; | |
private Dictionary<Type, IActivator> activators = new Dictionary<Type, IActivator>() | |
public SimpleContainer(Func<Type, object> missingHandler) { | |
_missingHandler = missingHandler; | |
} | |
public SimpleContainer() : this(t => throw new ContainerException(t.ToString() + " not found in container")) | |
{} | |
private object resolve(Type t) { | |
return activators.ContainsKey(t) ? activators[t].Activate : _missingHandler(t); | |
} | |
private object createInstance(Type t, Func<Type, obj> resolver) { | |
var sortedConstructors = t.GetConstructors().SortBy(c => -c.GetParamters().Length); | |
var result = sortedConstructors.Select(c => { | |
try { | |
var parameters = c.GetParameters().Select(p => resolver(p.ParameterType)).ToArray(); | |
return Activator.CreateInstance(t, parameters); | |
} | |
catch(ContainerException e) { } | |
return null; | |
}).FirstOrDefault(o => o != null); | |
if(result != null) | |
return result; | |
throw new ContainerException(t.ToString() + " does not have a satisfiable constructor"); | |
} | |
private object create(Type t) { return createInstance(t, resolve); } | |
private void addActivator (Type t, Func<object> f) { | |
if(activators.ContainsKey(t)) | |
throw new ContainerException(t.ToString() + " already added to container"); | |
else | |
activators.Add(t, new LazyActivator(f)); | |
} | |
private void add (Type i, Type c) { | |
addActivator(i, () => create(c)); | |
} | |
private void decorate (Type i, Type c) { | |
let existing = activators[i]; | |
activators.[i] = new LazyActivator(() => createInstance(c, t => t.Equals(i) ? existing.Activate() : resolve(t))); | |
} | |
public void Add<T>() { add(typeof(T), typeof(T)); } | |
public void Add<Interface, Component>() { add(typeof(Interface), typeof(Component)); } | |
public void Add<T>(Func<object> f) { addActivator(typeof(T), f); } | |
public T Resolve<T>() { return (T) resolve(typeof(T)); } | |
public object Resolve(Type t) { return resolve(t); } | |
public void Decorate<Interface, Decorator>() { decorate(typeof(Interface), typeof(Decorator)); } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment