Skip to content

Commit

Permalink
fix: find generic argument recursively
Browse files Browse the repository at this point in the history
  • Loading branch information
labbbirder committed Oct 9, 2023
1 parent 072d2b6 commit b90d1d3
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 25 deletions.
79 changes: 56 additions & 23 deletions Runtime/ClassicalUsages/ServiceContainer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace com.bbbirder.injection
{
Expand Down Expand Up @@ -30,41 +31,71 @@ public static void ClearInstances()
{
singletons.Clear();
}
static Type FindImplementSubclass(Type type)
{
if (type.IsAbstract || type.IsInterface)
{
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");
}
if (subtypes.Length > 1)
{
Debug.LogWarning($"type {type} exists more than one implements");
}
return subtypes[0];
}
return type;
}
static Type FindType(Type type)
{
if (!lutInfos.TryGetValue(type, out var info))
{
var resultType = type;
if (type.IsAbstract || type.IsInterface)
Type resultType = default;

if (type.IsGenericType)
{
var subtypes = Retriever.GetAllSubtypes(type)
.Append(type)
.Where(t => !t.IsInterface)
.Where(t => !t.IsAbstract)
.ToArray()
;
if (subtypes.Length == 0)
if (type.IsGenericTypeDefinition)
{
throw new ArgumentException($"type {type} doesn't has an implement");
throw new ArgumentException($"a unbound generic type {type}");
}
if (subtypes.Length > 1)
else
{
Debug.LogWarning($"type {type} exists more than one implements");
var unboundType = type.GetGenericTypeDefinition();
var unboundTypeArguments = unboundType.GetGenericArguments();

var resultTypeArguments = new Type[type.GenericTypeArguments.Length];
type.GenericTypeArguments.Select(FindType).ToArray();
for (var i = 0; i < type.GenericTypeArguments.Length; i++)
{
var typeArg = type.GenericTypeArguments[i];
var unboudnTypeArg = unboundTypeArguments[i];
var notImpl = typeArg.IsAbstract || typeArg.IsInterface;
Debug.Log($"{typeArg} {unboudnTypeArg} {notImpl} {unboudnTypeArg.GenericParameterAttributes} {(unboudnTypeArg.GenericParameterAttributes | GenericParameterAttributes.Covariant)}");
if (notImpl && (unboudnTypeArg.GenericParameterAttributes & GenericParameterAttributes.Covariant) == 0)
{
throw new($"type arg {unboudnTypeArg} must has a 'out' modifier in {unboundType}");
}
resultTypeArguments[i] = FindType(typeArg);
}
var unboundResultType = FindImplementSubclass(unboundType);
Debug.Log($"{unboundResultType} {resultTypeArguments.Length}");
resultType = unboundResultType.MakeGenericType(
resultTypeArguments
);
}
resultType = subtypes[0];
}

//TODO:Construct generic type recursively
//TODO:Take multiple generic type constraints into account
if (resultType.IsGenericType && resultType.IsGenericTypeDefinition)
else
{
var typeParams = resultType.GenericTypeArguments
.Select(a => a.GetGenericParameterConstraints()[0])
.Select(FindType)
.ToArray()
;
resultType = resultType.MakeGenericType(typeParams);
resultType = FindImplementSubclass(type);
}

lutInfos[type] = info = new Info()
{
resultType = resultType,
Expand All @@ -91,6 +122,8 @@ public static object Get(Type type)

public static T Get<T>()
{
var inst = Get(typeof(T));
Debug.Log($"inst {inst} to {typeof(T)}");
return (T)Get(typeof(T));
}

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.13",
"version": "1.3.14",
"hideInEditor": false,
"author": "bbbirder <[email protected]>",
"dependencies": {
"com.bbbirder.directattribute": "1.1.3",
"com.bbbirder.directattribute": "1.1.4",
"com.unity.nuget.mono-cecil": "1.10.2"
},
"samples": [
Expand Down

0 comments on commit b90d1d3

Please sign in to comment.