Last active
August 29, 2015 14:10
-
-
Save hanswolff/90896c0c2ed66f94c29a to your computer and use it in GitHub Desktop.
Very simple dependency injection framework (licensed under MIT license or do what you like with it)
This file contains hidden or 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
//// Example: | |
// | |
// using (var context = new MiniInjectionContext()) | |
// { | |
// context.Register<IMyInterfaceType>(c => new MyClassImplementingInterface()); | |
// | |
// var instance = context.Get<IMyInterfaceType>(); | |
// } | |
//} | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
public class MiniInjectionContext : IInjectionContext | |
{ | |
private readonly Dictionary<Type, Func<IInjectionContext, object>> _actions; | |
public MiniInjectionContext() | |
{ | |
_actions = new Dictionary<Type, Func<IInjectionContext, object>>(); | |
} | |
public MiniInjectionContext(MiniInjectionContext parentContext) | |
{ | |
if (parentContext == null) throw new ArgumentNullException("parentContext"); | |
_actions = parentContext._actions.ToDictionary(x => x.Key, x => x.Value); | |
} | |
public void Dispose() | |
{ | |
// just for convenience to create scopes with "using" | |
} | |
public T Get<T>() where T : class | |
{ | |
return (T) Get(typeof (T)); | |
} | |
public object Get(Type type) | |
{ | |
object result; | |
if (type.IsInterface) | |
{ | |
result = TryGetInterface(type); | |
if (result == null) | |
throw new InvalidOperationException( | |
String.Format("Type '{0}' not registered for Get(), please use Register<T> first", type.FullName)); | |
return result; | |
} | |
result = TryCreateFromConstructor(type); | |
if (result == null) | |
throw new InvalidOperationException( | |
String.Format("Type '{0}' cannot be instantiated as it must have a constructor with only interface parameters". type.FullName)); | |
return result; | |
} | |
public T TryGet<T>() where T : class | |
{ | |
return (T)TryGet(typeof (T)); | |
} | |
public object TryGet(Type type) | |
{ | |
if (type.IsInterface) | |
{ | |
return TryGetInterface(type); | |
} | |
return TryCreateFromConstructor(type); | |
} | |
private object TryGetInterface(Type type) | |
{ | |
Func<IInjectionContext, object> func; | |
if (!_actions.TryGetValue(type, out func)) | |
return null; | |
return func(this); | |
} | |
private object TryCreateFromConstructor(Type type) | |
{ | |
foreach (var ci in type.GetConstructors() | |
.Where(x => !x.IsGenericMethod) | |
.Where(x => x.GetParameters().All(p => p.ParameterType.IsInterface || p.ParameterType == typeof(MiniInjectionContext))) | |
.OrderBy(x => x.GetParameters().Length)) | |
{ | |
var parameters = ci.GetParameters().Select(p => | |
{ | |
if (p.ParameterType == typeof (MiniInjectionContext) || p.ParameterType == typeof (IInjectionContext)) | |
return this; | |
return Get(p.ParameterType); | |
}).ToArray(); | |
return ci.Invoke(parameters); | |
} | |
return null; | |
} | |
public void Register<T>(Func<IInjectionContext, T> createFunc) | |
{ | |
if (createFunc == null) throw new ArgumentNullException("createFunc"); | |
if (!typeof(T).IsInterface) | |
throw new InvalidOperationException(String.Format("Generic type <T> for Register<T> must be an interface (but type was: {0})", typeof(T).FullName)); | |
Func<IInjectionContext, object> registerAction = c => createFunc(c); | |
_actions[typeof(T)] = registerAction; | |
} | |
public IInjectionContext CreateScope() | |
{ | |
return new MiniInjectionContext(this); | |
} | |
} | |
public interface IInjectionContext : IDisposable | |
{ | |
T Get<T>() where T : class; | |
object Get(Type type); | |
T TryGet<T>() where T : class; | |
object TryGet(Type type); | |
void Register<T>(Func<IInjectionContext, T> createFunc) where T : class; | |
IInjectionContext CreateScope(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment