From ab79ef5b270bd71ee2790652db8939c4223f271a Mon Sep 17 00:00:00 2001 From: labbbirder <502100554@qq.com> Date: Fri, 1 Mar 2024 20:12:24 +0800 Subject: [PATCH] feat: ServiceContainer returns type sorted by inherit distance --- Runtime/ClassicalUsages/OrderDIAttribute.cs | 1 + Runtime/ClassicalUsages/ServiceContainer.cs | 85 +++++++++++++++------ package.json | 4 +- 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/Runtime/ClassicalUsages/OrderDIAttribute.cs b/Runtime/ClassicalUsages/OrderDIAttribute.cs index 8d3b60a..ad620f5 100644 --- a/Runtime/ClassicalUsages/OrderDIAttribute.cs +++ b/Runtime/ClassicalUsages/OrderDIAttribute.cs @@ -3,6 +3,7 @@ namespace com.bbbirder.injection { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] public class OrderDIAttribute : Attribute { internal int order; diff --git a/Runtime/ClassicalUsages/ServiceContainer.cs b/Runtime/ClassicalUsages/ServiceContainer.cs index d75eff7..ba199c4 100644 --- a/Runtime/ClassicalUsages/ServiceContainer.cs +++ b/Runtime/ClassicalUsages/ServiceContainer.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using UnityEngine; + namespace com.bbbirder.injection { using static ServiceScopeMode; @@ -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()?.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()?.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); @@ -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; } diff --git a/package.json b/package.json index c1c8f24..d71194e 100644 --- a/package.json +++ b/package.json @@ -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 <502100554@qq.com>", "dependencies": { - "com.bbbirder.directattribute": "1.1.5", + "com.bbbirder.directattribute": "1.1.8", "com.unity.nuget.mono-cecil": "1.10.2" }, "samples": [