Skip to content

Instantly share code, notes, and snippets.

@JakubNei
Last active June 8, 2023 17:15
Show Gist options
  • Save JakubNei/d20067cd0c5f8b6b5d0ace607152d810 to your computer and use it in GitHub Desktop.
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
using System;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class DependencyAttribute : Attribute
{
}
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