Merge pull request #417 from RogueException/feature/better-di
Enhance Dependency Injection
This commit is contained in:
@@ -5,27 +5,59 @@ namespace Discord.Commands
|
||||
{
|
||||
public class DependencyMap : IDependencyMap
|
||||
{
|
||||
private Dictionary<Type, object> map;
|
||||
private Dictionary<Type, Func<object>> map;
|
||||
|
||||
public static DependencyMap Empty => new DependencyMap();
|
||||
|
||||
public DependencyMap()
|
||||
{
|
||||
map = new Dictionary<Type, object>();
|
||||
map = new Dictionary<Type, Func<object>>();
|
||||
}
|
||||
|
||||
public void Add<T>(T obj)
|
||||
/// <inheritdoc />
|
||||
public void Add<T>(T obj) where T : class
|
||||
=> AddFactory(() => obj);
|
||||
/// <inheritdoc />
|
||||
public bool TryAdd<T>(T obj) where T : class
|
||||
=> TryAddFactory(() => obj);
|
||||
/// <inheritdoc />
|
||||
public void AddTransient<T>() where T : class, new()
|
||||
=> AddFactory(() => new T());
|
||||
/// <inheritdoc />
|
||||
public bool TryAddTransient<T>() where T : class, new()
|
||||
=> TryAddFactory(() => new T());
|
||||
/// <inheritdoc />
|
||||
public void AddTransient<TKey, TImpl>() where TKey : class
|
||||
where TImpl : class, TKey, new()
|
||||
=> AddFactory<TKey>(() => new TImpl());
|
||||
public bool TryAddTransient<TKey, TImpl>() where TKey : class
|
||||
where TImpl : class, TKey, new()
|
||||
=> TryAddFactory<TKey>(() => new TImpl());
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddFactory<T>(Func<T> factory) where T : class
|
||||
{
|
||||
var t = typeof(T);
|
||||
if (map.ContainsKey(t))
|
||||
throw new InvalidOperationException($"The dependency map already contains \"{t.FullName}\"");
|
||||
map.Add(t, obj);
|
||||
map.Add(t, factory);
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public bool TryAddFactory<T>(Func<T> factory) where T : class
|
||||
{
|
||||
var t = typeof(T);
|
||||
if (map.ContainsKey(t))
|
||||
return false;
|
||||
map.Add(t, factory);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T Get<T>()
|
||||
{
|
||||
return (T)Get(typeof(T));
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public object Get(Type t)
|
||||
{
|
||||
object result;
|
||||
@@ -35,6 +67,7 @@ namespace Discord.Commands
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGet<T>(out T result)
|
||||
{
|
||||
object untypedResult;
|
||||
@@ -49,9 +82,17 @@ namespace Discord.Commands
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public bool TryGet(Type t, out object result)
|
||||
{
|
||||
return map.TryGetValue(t, out result);
|
||||
Func<object> func;
|
||||
if (map.TryGetValue(t, out func))
|
||||
{
|
||||
result = func();
|
||||
return true;
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,86 @@ namespace Discord.Commands
|
||||
{
|
||||
public interface IDependencyMap
|
||||
{
|
||||
void Add<T>(T obj);
|
||||
/// <summary>
|
||||
/// Add an instance of a service to be injected.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of service.</typeparam>
|
||||
/// <param name="obj">The instance of a service.</param>
|
||||
void Add<T>(T obj) where T : class;
|
||||
/// <summary>
|
||||
/// Tries to add an instance of a service to be injected.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of service.</typeparam>
|
||||
/// <param name="obj">The instance of a service.</param>
|
||||
/// <returns>A bool, indicating if the service was successfully added to the DependencyMap.</returns>
|
||||
bool TryAdd<T>(T obj) where T : class;
|
||||
/// <summary>
|
||||
/// Add a service that will be injected by a new instance every time.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of instance to inject.</typeparam>
|
||||
void AddTransient<T>() where T : class, new();
|
||||
/// <summary>
|
||||
/// Tries to add a service that will be injected by a new instance every time.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of instance to inject.</typeparam>
|
||||
/// <returns>A bool, indicating if the service was successfully added to the DependencyMap.</returns>
|
||||
bool TryAddTransient<T>() where T : class, new();
|
||||
/// <summary>
|
||||
/// Add a service that will be injected by a new instance every time.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type to look for when injecting.</typeparam>
|
||||
/// <typeparam name="TImpl">The type to inject when injecting.</typeparam>
|
||||
/// <example>
|
||||
/// map.AddTransient<IService, Service>
|
||||
/// </example>
|
||||
void AddTransient<TKey, TImpl>() where TKey: class where TImpl : class, TKey, new();
|
||||
/// <summary>
|
||||
/// Tries to add a service that will be injected by a new instance every time.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type to look for when injecting.</typeparam>
|
||||
/// <typeparam name="TImpl">The type to inject when injecting.</typeparam>
|
||||
/// <returns>A bool, indicating if the service was successfully added to the DependencyMap.</returns>
|
||||
bool TryAddTransient<TKey, TImpl>() where TKey : class where TImpl : class, TKey, new();
|
||||
/// <summary>
|
||||
/// Add a service that will be injected by a factory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to look for when injecting.</typeparam>
|
||||
/// <param name="factory">The factory that returns a type of this service.</param>
|
||||
void AddFactory<T>(Func<T> factory) where T : class;
|
||||
/// <summary>
|
||||
/// Tries to add a service that will be injected by a factory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to look for when injecting.</typeparam>
|
||||
/// <param name="factory">The factory that returns a type of this service.</param>
|
||||
/// <returns>A bool, indicating if the service was successfully added to the DependencyMap.</returns>
|
||||
bool TryAddFactory<T>(Func<T> factory) where T : class;
|
||||
|
||||
/// <summary>
|
||||
/// Pull an object from the map.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of service.</typeparam>
|
||||
/// <returns>An instance of this service.</returns>
|
||||
T Get<T>();
|
||||
/// <summary>
|
||||
/// Try to pull an object from the map.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of service.</typeparam>
|
||||
/// <param name="result">The instance of this service.</param>
|
||||
/// <returns>Whether or not this object could be found in the map.</returns>
|
||||
bool TryGet<T>(out T result);
|
||||
|
||||
/// <summary>
|
||||
/// Pull an object from the map.
|
||||
/// </summary>
|
||||
/// <param name="t">The type of service.</param>
|
||||
/// <returns>An instance of this service.</returns>
|
||||
object Get(Type t);
|
||||
/// <summary>
|
||||
/// Try to pull an object from the map.
|
||||
/// </summary>
|
||||
/// <param name="t">The type of service.</param>
|
||||
/// <param name="result">An instance of this service.</param>
|
||||
/// <returns>Whether or not this object could be found in the map.</returns>
|
||||
bool TryGet(Type t, out object result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ namespace Discord.Commands
|
||||
|
||||
try
|
||||
{
|
||||
return (T)constructor.Invoke(args);
|
||||
T instance = (T)constructor.Invoke(args);
|
||||
return instance;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user