Skip to content

Commit

Permalink
feat: ServiceContainer returns type sorted by inherit distance
Browse files Browse the repository at this point in the history
  • Loading branch information
labbbirder committed Mar 1, 2024
1 parent 7a680b6 commit ab79ef5
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 27 deletions.
1 change: 1 addition & 0 deletions Runtime/ClassicalUsages/OrderDIAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace com.bbbirder.injection
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
public class OrderDIAttribute : Attribute
{
internal int order;
Expand Down
85 changes: 60 additions & 25 deletions Runtime/ClassicalUsages/ServiceContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace com.bbbirder.injection
{
using static ServiceScopeMode;
Expand Down Expand Up @@ -32,39 +33,73 @@ public static void ClearInstances()
{
singletons.Clear();
}
static Type FindImplementSubclass(Type type)

public static int GetDeriveDistance(Type subType, Type baseType)
{
if (type.IsAbstract || type.IsInterface)
if ((baseType ?? subType) == null) return 0;
if (baseType == null) return -1;
if (baseType.IsInterface)
{
var subtypes = Retriever.GetAllSubtypes(type)
.Append(type)
.Where(t => !t.IsInterface)
.Where(t => !t.IsAbstract)
.ToArray()
;
if (subtypes.Length == 0)
var dist = -1;
while (subType != null && subType.GetInterfaces().Contains(baseType))
{
// throw new ArgumentException($"type {type} doesn't has an implement");
return null;
subType = subType.BaseType;
dist++;
}
if (subtypes.Length > 1)
return dist;
}
else
{
var dist = 0;
while (subType != baseType)
{
var orderedTypeGroups = subtypes
.GroupBy(tp => tp.GetCustomAttribute<OrderDIAttribute>()?.order ?? 0)
.OrderBy(g => g.Key);
foreach (var g in orderedTypeGroups)
{
if (g.Count() > 1)
{
Debug.LogWarning($"type {type} exists more than one implements, sharing a priority order {g.Key}: {string.Join(",", g.AsEnumerable().Select(t => t.FullName))}");
}
return g.First();
}
if (subType is null) return -1;
subType = subType.BaseType;
dist++;
}
return dist;
}
}

static Type FindImplementSubclass(Type type)
{
if (type.IsSealed) return type;

var subtypes = Retriever.GetAllSubtypes(type)
.Append(type)
.Where(t => !t.IsInterface)
.Where(t => !t.IsAbstract)
.ToArray()
;
if (subtypes.Length == 0)
{
// throw new ArgumentException($"type {type} doesn't has an implement");
return null;
}
if (subtypes.Length == 1)
{
return subtypes[0];
}
return type;
var minOrdered = subtypes
.GroupBy(t => t.GetCustomAttribute<OrderDIAttribute>()?.order ?? 0)
.OrderBy(g => g.Key)
.First()
.ToArray();
if (minOrdered.Length > 1)
{
minOrdered = minOrdered
.GroupBy(t => GetDeriveDistance(t, type))
.OrderBy(g => -g.Key)
.First()
.ToArray();
}
if (minOrdered.Length > 1)
{
Debug.LogWarning($"type {type} exists more than one implements: {string.Join(",", minOrdered.Select(t => t.FullName))}");
}
return minOrdered[0];
}

static Type FindTargetType(Type type)
{
if (!type.IsGenericType) return FindImplementSubclass(type);
Expand Down Expand Up @@ -161,7 +196,7 @@ public static object Get(Type desiredType, Type declaringType = null, bool throw

if (info.resultType is null)
{
if(throwOnNoImplementations)
if (throwOnNoImplementations)
throw new ArgumentException($"type {desiredType} doesn't has an implement");
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"name": "com.bbbirder.injection",
"displayName": "Unity Injection",
"description": "Unity注入模块,可以运行时改变被注入函数实现。",
"version": "1.3.24",
"version": "1.3.29",
"hideInEditor": false,
"author": "bbbirder <[email protected]>",
"dependencies": {
"com.bbbirder.directattribute": "1.1.5",
"com.bbbirder.directattribute": "1.1.8",
"com.unity.nuget.mono-cecil": "1.10.2"
},
"samples": [
Expand Down

0 comments on commit ab79ef5

Please sign in to comment.