Last active
June 8, 2023 17:15
-
-
Save JakubNei/d20067cd0c5f8b6b5d0ace607152d810 to your computer and use it in GitHub Desktop.
Beginnings of simple one dependency injection. For: https://github.com/aeroson/mcs-ICodeCompiler/issues/6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] | |
public class DependencyAttribute : Attribute | |
{ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Reflection; | |
using System.Linq; | |
using System.Collections; | |
using System; | |
public class DependencyManager | |
{ | |
HashSet<object> instances = new HashSet<object>(); | |
HashSet<Type> registeredTypes = new HashSet<Type>(); | |
public void Register(params object[] instances) | |
{ | |
foreach (var instance in instances) | |
{ | |
instances.Add(instance); | |
} | |
} | |
public void Register<T>(T instance) | |
{ | |
Register(instance); | |
} | |
public void RegisterType<TManager>() where TManager : new() | |
{ | |
registeredTypes.Add(typeof(TManager)); | |
} | |
/// <summary> | |
/// Get instance of type | |
/// </summary> | |
/// <param name="type"></param> | |
/// <returns></returns> | |
public object GetInstance(Type type) | |
{ | |
object instance = instances.FirstOrDefault(i => | |
{ | |
var t = i.GetType(); | |
return | |
t == type || | |
t.IsSubclassOf(type) || | |
t.GetInterfaces().Contains(type); | |
}); | |
if (instance == null) | |
{ | |
var typeToInstantiate = registeredTypes.FirstOrDefault(t => | |
t == type || | |
t.IsSubclassOf(type) || | |
t.GetInterfaces().Contains(type) | |
); | |
if (typeToInstantiate == null) | |
{ | |
throw new Exception("no registered type or instance found for " + type); | |
} | |
instance = Activator.CreateInstance(typeToInstantiate); | |
Resolve(instance); | |
Register(instance); | |
} | |
return instance; | |
} | |
/// <summary> | |
/// Assignes instances to members that are null and marked with DependencyAttribute, | |
/// </summary> | |
/// <param name="instance"></param> | |
public void Resolve(object instance) | |
{ | |
var members = instance.GetType().GetMembers( | |
BindingFlags.Instance | | |
BindingFlags.Public | BindingFlags.NonPublic | | |
BindingFlags.GetProperty | BindingFlags.SetProperty | | |
BindingFlags.FlattenHierarchy | |
).Where(m => m.GetCustomAttributes(typeof(DependencyAttribute), true) != null); | |
foreach(var member in members) | |
{ | |
var prop = member as PropertyInfo; | |
var field = member as FieldInfo; | |
if (prop != null) | |
{ | |
if (prop.GetValue(instance, null) == null) | |
{ | |
var resolvedMemberValue = GetInstance(member.ReflectedType); | |
prop.SetValue(instance, resolvedMemberValue, null); | |
} | |
} | |
if (field != null) | |
{ | |
if (field.GetValue(instance) == null) | |
{ | |
var resolvedMemberValue = GetInstance(member.ReflectedType); | |
field.SetValue(instance, resolvedMemberValue); | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Creates new instance and then resolves it's dependencies. | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <returns></returns> | |
public T Resolve<T>() where T : new() | |
{ | |
var ret = new T(); | |
Resolve(ret); | |
return ret; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment