Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[异常] (装饰器) 函数参数泛型自带 UnityEngine.Object 抛异常 #4

Closed
xinansky opened this issue Mar 31, 2024 · 3 comments
Closed

Comments

@xinansky
Copy link

xinansky commented Mar 31, 2024

示例:
函数A:public static void LoadSubAssets(string location, Action<Object[]> cb)
函数B:public static void LoadSubAssets(string location, Type type, Action<Object[]> cb)
函数C:public static void LoadSubAssets(string location, Action<TObject[]> cb) where TObject : Object
给函数B加上自定义装饰器实现了 DecoratorAttribute 的属性 并开始编译
会抛出异常 信息如下
Exception: Cannot find Method LoadSubAssets in Type xxxx_class
报错库函数: InjectHelper.cs FindMethod td.Methods.FirstOrDefault(m => m.GetSignature() == methodSignature) == null
Unity版本 2022.3.8f1

@xinansky xinansky changed the title [异常] (装饰器) 函数重载会导致查找函数失败 [异常] (装饰器) 函数参数泛型自带 UnityEngine.Object 抛异常 Mar 31, 2024
@xinansky
Copy link
Author

原因已经找到 MethodBase.GetSignature函数与MethodDefinition.GetSignature函数判断值出现不一致
目前使用 (MethodDefinition)a.MetadataToken.ToInt32() 和 (MethodBase)b.MetadataToken 作为判断值

internal static MethodReference FindMethod(this TypeDefinition td, MethodBase methodSignature)
{
      return (from method in td.Methods
            where method.MetadataToken.ToInt32() == methodSignature.MetadataToken
            select td.Module?.ImportReference(method)).FirstOrDefault();
}

@labbbirder
Copy link
Owner

@xinansky 感谢fix,下个版本修正

@labbbirder
Copy link
Owner

原因已经找到 MethodBase.GetSignature函数与MethodDefinition.GetSignature函数判断值出现不一致 目前使用 (MethodDefinition)a.MetadataToken.ToInt32() 和 (MethodBase)b.MetadataToken 作为判断值

internal static MethodReference FindMethod(this TypeDefinition td, MethodBase methodSignature)
{
      return (from method in td.Methods
            where method.MetadataToken.ToInt32() == methodSignature.MetadataToken
            select td.Module?.ImportReference(method)).FirstOrDefault();
}

MetadataToken是一种很聪明的做法,但新的修复还是使用签名的方式实现,原因有下:

  1. 考虑到UnityInjection在注入时加载的Assembly和目标Assembly虽然AssemblyName相同,但有时不是同一个(通常是那些有变种的预编译程序集Precompiled Assemblies with variants),对于这种情况两者的MetadataToken很有可能是不一致的。当然,这种不一致的情况只发生在Runtime,Editor下是无法察觉的。
  2. 签名的验证只发生在Editor构建时,不对运行时产生负载。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants