60 lines
1.9 KiB
C#
60 lines
1.9 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Reflection;
|
||
|
|
|
||
|
|
namespace BracerLib.DI
|
||
|
|
{
|
||
|
|
public class DependencyProvider
|
||
|
|
{
|
||
|
|
private IDictionary<Type, Dependency> dependencyMap = new Dictionary<Type, Dependency>();
|
||
|
|
private IDictionary<Type, object> singletons = new Dictionary<Type, object>();
|
||
|
|
|
||
|
|
public DependencyProvider(DependencyCollection collection)
|
||
|
|
{
|
||
|
|
foreach (var d in collection)
|
||
|
|
dependencyMap.Add(d.Type, d);
|
||
|
|
}
|
||
|
|
|
||
|
|
public object Get(Type type)
|
||
|
|
{
|
||
|
|
if (!dependencyMap.ContainsKey(type))
|
||
|
|
throw new ArgumentException($"Type is not a dependency: {type.FullName}");
|
||
|
|
|
||
|
|
var dependency = dependencyMap[type];
|
||
|
|
switch (dependency.Lifetime)
|
||
|
|
{
|
||
|
|
case DependencyLifetime.Transient: return dependency.Factory(this);
|
||
|
|
case DependencyLifetime.Singleton:
|
||
|
|
if (!singletons.ContainsKey(type))
|
||
|
|
singletons.Add(type, dependency.Factory(this));
|
||
|
|
|
||
|
|
return singletons[type];
|
||
|
|
default: throw new ArgumentOutOfRangeException($"Unavailable lifetime for dependency: {type.FullName}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public T Get<T>() => (T)Get(typeof(T));
|
||
|
|
|
||
|
|
public object Inject(object dependant)
|
||
|
|
{
|
||
|
|
var type = dependant.GetType();
|
||
|
|
while (type != null)
|
||
|
|
{
|
||
|
|
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly |
|
||
|
|
BindingFlags.Instance);
|
||
|
|
foreach (var f in fields)
|
||
|
|
{
|
||
|
|
if (f.GetCustomAttribute<InjectFieldAttribute>(false) == null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
f.SetValue(dependant, Get(f.FieldType));
|
||
|
|
}
|
||
|
|
|
||
|
|
type = type.BaseType;
|
||
|
|
}
|
||
|
|
|
||
|
|
return dependant;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|