Skip to content

Commit

Permalink
feat: add very basic dependency injection
Browse files Browse the repository at this point in the history
  • Loading branch information
jonisavo committed Apr 27, 2022
1 parent 6d88e77 commit dc12f9d
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 16 deletions.
62 changes: 62 additions & 0 deletions Core/DependencyInjector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;

namespace UIComponents.Core
{
public class DependencyInjector
{
private static readonly Dictionary<Type, object> InstantiatedInstanceDictionary
= new Dictionary<Type, object>();

private readonly Dictionary<Type, object> _dependencyDictionary
= new Dictionary<Type, object>();

internal void AddProvidersFromDependencies(IEnumerable<InjectDependencyAttribute> dependencyAttributes)
{
foreach (var dependencyAttribute in dependencyAttributes)
{
var type = dependencyAttribute.DependencyType;
var providerType = dependencyAttribute.ProviderType;

if (!_dependencyDictionary.ContainsKey(type))
_dependencyDictionary[type] = CreateInstance(providerType);
}
}

private static object CreateInstance(Type providerType)
{
object instance;

if (InstantiatedInstanceDictionary.ContainsKey(providerType))
{
instance = InstantiatedInstanceDictionary[providerType];
}
else
{
instance = Activator.CreateInstance(providerType);
InstantiatedInstanceDictionary[providerType] = instance;
}

return instance;
}

public void SetProvider<T>(T instance)
{
_dependencyDictionary[typeof(T)] = instance;
}

public T Provide<T>()
{
var type = typeof(T);

if (!_dependencyDictionary.ContainsKey(type))
{
var value = (T) CreateInstance(type);
SetProvider(value);
return value;
}

return (T) _dependencyDictionary[type];
}
}
}
3 changes: 3 additions & 0 deletions Core/DependencyInjector.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions Core/InjectDependencyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using JetBrains.Annotations;

namespace UIComponents.Core
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[BaseTypeRequired(typeof(UIComponent))]
public class InjectDependencyAttribute : Attribute
{
public readonly Type DependencyType;

public readonly Type ProviderType;

public InjectDependencyAttribute(Type dependency, Type provider)
{
DependencyType = dependency;
ProviderType = provider;
}
}
}
3 changes: 3 additions & 0 deletions Core/InjectDependencyAttribute.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 41 additions & 16 deletions Core/UIComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using UnityEditor;
using UnityEngine;
Expand All @@ -14,31 +15,39 @@ public abstract class UIComponent : VisualElement

private readonly StylesheetAttribute[] _stylesheetAttributes;

private static readonly Dictionary<Type, DependencyInjector> InjectorDictionary =
new Dictionary<Type, DependencyInjector>();

public static void SetDependencyProvider<TComponent, TDependency>(TDependency provider)
{
var componentType = typeof(TComponent);

if (!InjectorDictionary.ContainsKey(componentType))
InjectorDictionary.Add(componentType, new DependencyInjector());

InjectorDictionary[componentType].SetProvider(provider);
}

protected UIComponent()
{
_componentType = GetType();
_layoutAttribute = GetLayoutAttribute();
_stylesheetAttributes = GetStylesheetAttributes();
_stylesheetAttributes = GetAttributes<StylesheetAttribute>();

var type = GetType();

if (!InjectorDictionary.ContainsKey(type))
InjectorDictionary.Add(type, new DependencyInjector());

InjectorDictionary[type].AddProvidersFromDependencies(GetAttributes<InjectDependencyAttribute>());

LoadLayout();
LoadStyles();
}

[CanBeNull]
private LayoutAttribute GetLayoutAttribute()
{
var layoutAttributes =
(LayoutAttribute[]) _componentType.GetCustomAttributes(typeof(LayoutAttribute), true);

if (layoutAttributes.Length == 0)
return null;

return layoutAttributes[0];
}

private StylesheetAttribute[] GetStylesheetAttributes()
protected T Provide<T>()
{
return (StylesheetAttribute[])
_componentType.GetCustomAttributes(typeof(StylesheetAttribute), true);
return InjectorDictionary[_componentType].Provide<T>();
}

[CanBeNull]
Expand All @@ -62,6 +71,22 @@ protected virtual StyleSheet[] GetStyleSheets()

return loadedStyleSheets;
}

[CanBeNull]
private LayoutAttribute GetLayoutAttribute()
{
var layoutAttributes = GetAttributes<LayoutAttribute>();

if (layoutAttributes.Length == 0)
return null;

return layoutAttributes[0];
}

private T[] GetAttributes<T>() where T : Attribute
{
return (T[]) _componentType.GetCustomAttributes(typeof(T), true);
}

private void LoadLayout()
{
Expand Down

0 comments on commit dc12f9d

Please sign in to comment.