Skip to content

Commit

Permalink
Make Injector non-static
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Jul 1, 2018
1 parent e25db14 commit e610836
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 30 deletions.
14 changes: 8 additions & 6 deletions Jellyfish/DependencyInjection/InjectionResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public class InjectionResolver
/// </summary>
/// <typeparam name="T">The type to inject properties into</typeparam>
/// <param name="reference">A reference to the type to inject into (or null if static properties)</param>
public static void InjectProperties<T>(T reference)
/// <param name="injector">The injector instance to use</param>
public static void InjectProperties<T>(T reference, Injector injector)
{
var type = typeof(T);
var attributeType = typeof(DependencyAttribute);
Expand All @@ -28,8 +29,8 @@ public static void InjectProperties<T>(T reference)
var subType = typeArgument.Value as Type;
var parameters = paramsArgument.Value as object[];

Injector.Bind(property.PropertyType, subType, parameters);
var val = Injector.Initialize(property.PropertyType);
injector.Bind(property.PropertyType, subType, parameters);
var val = injector.Initialize(property.PropertyType);
property.SetValue(reference, val);
}
}
Expand All @@ -40,7 +41,8 @@ public static void InjectProperties<T>(T reference)
/// </summary>
/// <typeparam name="T">The type to inject fields into</typeparam>
/// <param name="reference">A reference to the type to inject into (or null if static fields)</param>
public static void InjectFields<T>(T reference)
/// <param name="injector">The injector instance to use</param>
public static void InjectFields<T>(T reference, Injector injector)
{
var type = typeof(T);
var attributeType = typeof(DependencyAttribute);
Expand All @@ -56,8 +58,8 @@ public static void InjectFields<T>(T reference)
var subType = typeArgument.Value as Type;
var parameters = paramsArgument.Value as object[];

Injector.Bind(field.FieldType, subType, parameters);
var val = Injector.Initialize(field.FieldType);
injector.Bind(field.FieldType, subType, parameters);
var val = injector.Initialize(field.FieldType);
field.SetValue(reference, val);
}
}
Expand Down
57 changes: 33 additions & 24 deletions Jellyfish/DependencyInjection/Injector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ namespace Jellyfish.DependencyInjection
/// </summary>
public class Injector
{
static Injector()
/// <summary>
/// Initialize a new <see cref="Injector"/> instance
/// </summary>
public Injector()
{
Instances = new Dictionary<Type, object>();
Templates = new Dictionary<Type, Func<object>>();
}

private static Dictionary<Type, object> Instances { get; }
private static Dictionary<Type, Func<object>> Templates { get; }
private Dictionary<Type, object> Instances { get; }
private Dictionary<Type, Func<object>> Templates { get; }

/// <summary>
/// Set the base type `<see cref="baseType" />` to use implementations of type `<see cref="subType" />`
Expand All @@ -32,7 +35,7 @@ static Injector()
/// Thrown if the type `<see cref="baseType" />`/`<see cref="subType" />` could
/// not be bound
/// </exception>
public static void Bind(Type baseType, Type subType, params object[] arguments)
public void Bind(Type baseType, Type subType, params object[] arguments)
{
if (!baseType.IsAssignableFrom(subType))
throw new ArgumentException($"The type {subType.Name} does not inherit from/implement {baseType.Name}");
Expand All @@ -47,53 +50,65 @@ public static void Bind(Type baseType, Type subType, params object[] arguments)
}

/// <summary>
/// Set the base type `<see cref="TBase" />` to use implementations of type `<see cref="TSubclass" />`
/// Set the base type `<see cref="TBase" />` to use implementations of type `<see cref="TSubtype" />`
/// </summary>
/// <typeparam name="TBase">The type of the base ([abstract] class or interface)</typeparam>
/// <typeparam name="TSubclass">The type of the sub-class (has to inherit from <see cref="TBase" />)</typeparam>
/// <typeparam name="TSubtype">The type of the sub-class (has to inherit from <see cref="TBase" />)</typeparam>
/// <param name="arguments">
/// The arguments to use for the `<see cref="TSubclass" />` constructor call (or <code>null</code>
/// The arguments to use for the `<see cref="TSubtype" />` constructor call (or <code>null</code>
/// if none)
/// </param>
/// <exception cref="InjectorStoreException">
/// Thrown if the type `<see cref="TBase" />`/`<see cref="TSubclass" />` could not
/// Thrown if the type `<see cref="TBase" />`/`<see cref="TSubtype" />` could not
/// be bound
/// </exception>
public static void Bind<TBase, TSubclass>(params object[] arguments) where TSubclass : TBase =>
Bind(typeof(TBase), typeof(TSubclass), arguments);
public void Bind<TBase, TSubtype>(params object[] arguments) where TSubtype : TBase =>
Bind(typeof(TBase), typeof(TSubtype), arguments);

/// <summary>
/// Declare a template for the given type `<see cref="TBase" />` on how to initialize a variable spontaneously
/// </summary>
/// <typeparam name="TBase">The type of the property or field that gets injected</typeparam>
/// <typeparam name="TSubtype">The `<see cref="TBase"/>`'s sub type to be used for initialization of the base</typeparam>
/// <param name="initializer">The function to call everytime a property or field has to get initialized</param>
/// <exception cref="InjectorStoreException">Thrown if the type `<see cref="TBase" />` could not be templated</exception>
public static void Template<TBase>(Func<TBase> initializer)
public void Template<TBase, TSubtype>(Func<TSubtype> initializer) where TSubtype : TBase
{
Templates.AddOrUpdate(typeof(TBase), initializer as Func<object>);
}

/// <summary>
/// Declare a template for the given type `<see cref="baseType" />` on how to initialize a variable spontaneously
/// </summary>
/// <param name="baseType">The type of the property or field that gets injected</param>
/// <param name="initializer">The function to call everytime a property or field has to get initialized</param>
/// <exception cref="InjectorStoreException">Thrown if the type `<see cref="baseType" />` could not be templated</exception>
public void Template(Type baseType, Func<object> initializer)
{
Templates.AddOrUpdate(baseType, initializer);
}

/// <summary>
/// Declare a fixed variable for the given type `<see cref="TBase" />` to set all variables of type `
/// <see cref="TBase" />` to
/// </summary>
/// <typeparam name="TBase">The type of the property or field that gets injected</typeparam>
/// <param name="instance">The static instance to initialize all variables of type `<see cref="TBase" />` with</param>
/// <exception cref="InjectorStoreException">Thrown if the type `<see cref="TBase" />` could not be defined</exception>
public static void Define<TBase>(TBase instance)
public void Define<TBase>(TBase instance)
{
Instances.AddOrUpdate(typeof(TBase), instance);
}

/// <summary>
/// Declare a fixed variable for the given type `<see cref="TBase" />` to set all variables of type `
/// Declare a fixed variable for the given type `<see cref="TSubtype" />` to set all variables of type `
/// <see cref="TBase" />` to
/// </summary>
/// <typeparam name="TBase">The type of the property or field that gets injected</typeparam>
/// <typeparam name="TSubtype">The type of the value to inject the property or field with</typeparam>
/// <param name="instance">The static instance to initialize all variables of type `<see cref="TBase" />` with</param>
/// <exception cref="InjectorStoreException">Thrown if the type `<see cref="TBase" />` could not be defined</exception>
public static void Define<TBase, TSubtype>(TSubtype instance) where TSubtype : TBase
public void Define<TBase, TSubtype>(TSubtype instance) where TSubtype : TBase
{
Instances.AddOrUpdate(typeof(TBase), instance);
}
Expand All @@ -107,16 +122,10 @@ public static void Define<TBase, TSubtype>(TSubtype instance) where TSubtype : T
/// the <see cref="Injector" />
/// </exception>
/// <returns>An initialized instance of type `<see cref="TBase" />`</returns>
public static TBase Initialize<TBase>() where TBase : class
public TBase Initialize<TBase>()
{
var type = typeof(TBase);

if (Instances.ContainsKey(type))
return Instances[type] as TBase;
if (Templates.ContainsKey(type))
return Templates[type]() as TBase;
throw new ArgumentException(
$"No implementations for the type {type.Name} could be found in the {nameof(Injector)}!");
return (TBase) Initialize(type);
}

/// <summary>
Expand All @@ -128,7 +137,7 @@ public static TBase Initialize<TBase>() where TBase : class
/// the <see cref="Injector" />
/// </exception>
/// <returns>An initialized instance of type `<see cref="type" />`</returns>
public static object Initialize(Type type)
public object Initialize(Type type)
{
if (Instances.ContainsKey(type))
return Instances[type];
Expand All @@ -141,7 +150,7 @@ public static object Initialize(Type type)
/// <summary>
/// Clear all templates, definitions and bindings in this <see cref="Injector"/>
/// </summary>
public static void Clear()
public void Clear()
{
Templates.Clear();
Instances.Clear();
Expand Down
1 change: 1 addition & 0 deletions Jellyfish/Jellyfish.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<ItemGroup>
<Compile Include="Attributes\ImplementationAttribute.cs" />
<Compile Include="Attributes\DependencyAttribute.cs" />
<Compile Include="DependencyInjection\InjectionExtensions.cs" />
<Compile Include="DependencyInjection\InjectionResolver.cs" />
<Compile Include="Extensions\DictionaryExtensions.cs" />
<Compile Include="DependencyInjection\Injector.cs" />
Expand Down

0 comments on commit e610836

Please sign in to comment.