Skip to content

Instantly share code, notes, and snippets.

@jamesfoster
Created May 19, 2010 15:19
Show Gist options
  • Save jamesfoster/406407 to your computer and use it in GitHub Desktop.
Save jamesfoster/406407 to your computer and use it in GitHub Desktop.
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