Skip to content

Instantly share code, notes, and snippets.

@DominicFinn
Last active April 5, 2016 09:14
Show Gist options
  • Save DominicFinn/d3a2a1a29d9547e159cbf313749fabb4 to your computer and use it in GitHub Desktop.
Save DominicFinn/d3a2a1a29d9547e159cbf313749fabb4 to your computer and use it in GitHub Desktop.
A mini IoC just for lulz
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using NUnit.Framework;
namespace JustForLulz
{
public interface ICat
{
}
public class Felix : ICat
{
}
public class Garfield : ICat
{
}
public interface ICatHouse
{
}
class CatHouse : ICatHouse
{
private readonly ICat cat;
public CatHouse(ICat cat)
{
this.cat = cat;
}
}
[TestFixture]
class Setup
{
[Test]
public void EmptyCtor()
{
MiniIoC.Bind<ICat, Felix>();
var felix = MiniIoC.GetInstance<ICat>();
Assert.NotNull(felix);
}
[Test]
public void CtorWithParams()
{
MiniIoC.Bind<ICat, Felix>();
MiniIoC.Bind<ICatHouse, CatHouse>();
var house = MiniIoC.GetInstance<ICatHouse>();
Assert.NotNull(house);
}
[Test]
public void AllTypes()
{
MiniIoC.Bind<ICat, Felix>();
MiniIoC.Bind<ICat, Garfield>();
var cats = MiniIoC.GetAllInstances<ICat>();
Assert.AreEqual(2, cats.Count());
}
}
public static class MiniIoC
{
private static readonly IDictionary<Type, IEnumerable<Type>> Types = new Dictionary<Type, IEnumerable<Type>>();
public static void Bind<TKey, TValue>() where TValue : TKey
{
if (Types.ContainsKey(typeof (TKey)))
{
Types[typeof (TKey)] = Types[typeof (TKey)].Union(new[] {typeof (TValue)});
}
else
{
Types.Add(typeof(TKey), new[] { typeof(TValue) });
}
}
public static IEnumerable<TKey> GetAllInstances<TKey>()
{
return Types[typeof (TKey)].Select(GetInstance<TKey>);
}
private static TKey GetInstance<TKey>(Type type)
{
var constructors = type.GetConstructors();
var longestConstructor = constructors.OrderByDescending(c => c.GetParameters().Length).First();
var paramObjects = longestConstructor.GetParameters().Select(p =>
{
var parameterType = p.ParameterType;
var getInstanceMethod = typeof(MiniIoC)
.GetMethod("GetInstance")
.MakeGenericMethod(parameterType);
var instanceObject = getInstanceMethod.Invoke(null, null);
return instanceObject;
});
if (paramObjects.Any())
{
return (TKey)System.Activator.CreateInstance(type, paramObjects.ToArray());
}
else
{
return (TKey)System.Activator.CreateInstance(type);
}
}
public static TKey GetInstance<TKey>()
{
if (Types[typeof(TKey)].Count() > 1)
{
throw new InvalidOperationException($"More than 1 type is registered for the type `{typeof (TKey)}`");
}
return GetInstance<TKey>(Types[typeof (TKey)].First());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment