Если вам не нужно ничего необычного, контейнер DI может быть очень коротким:
public class Container
{
private readonly Dictionary<Type,Func<Container,object>> factories;
private readonly Dictionary<Type,object> cache;
public Container()
{
this.factories = new Dictionary<Type,Func<Container,object>>();
this.cache = new Dictionary<Type,object>();
}
public void Register<TContract>(Func<Container,TContract> factory)
{
// wrap in lambda which returns object instead of TContract
factories[typeof(TContract)] = c => factory(c);
}
public TContract Get<TContract>()
{
var contract = typeof(TContract);
if (!cache.ContainsKey(contract))
{
this.cache[contract] = this.factories[contract](this);
}
return (TContract)this.cache[contract];
}
}
Что бы вы использовали, как это:
var container = new Container();
container.Register<ICar>(c => new Car(
c.Get<IEngine>(), c.Get<IWheel>()));
container.Register<IWheel>(c => new Wheel());
container.Register<IEngine>(c => new Engine());
var car = container.Get<ICar>();
Еще более минималистичным было бы сделать внедрение зависимостей без контейнера:
IWheel wheel = new Wheel();
IEngine engine = new Engine();
ICar car = new Car(engine, wheel);
Однако для сложных графов объектов может быстро усложниться поддержание правильного порядка построения во время рефакторингов. Контейнер не имеет этой проблемы.