You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#创建SetDllImportResolver委托报签名不兼容异常排查

问题描述

执行代码时抛出ArgumentException异常,异常信息为:
Cannot bind to the target method because its signature is not compatible with that of the delegate type(无法绑定到目标方法,因其签名与委托类型签名不兼容)

触发异常的相关代码如下:

private const string ReferencedAssemblyName = "System.Private.CoreLib";

private delegate IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath);
private delegate void SetDllImportResolverDelegate(Assembly assembly, DllImportResolver resolver);

private static readonly SetDllImportResolverDelegate _setDllImportResolverCallback;

static Program()
{
    Assembly coreLibAssembly = AppDomain.CurrentDomain
        .GetAssemblies()
        .FirstOrDefault((assembly) => assembly.GetName().Name == ReferencedAssemblyName);

    if (coreLibAssembly != null)
    {
        MethodInfo[] methods = coreLibAssembly
            .GetTypes()
            .FirstOrDefault((type) => type.Name == "NativeLibrary")
            .GetMethods(BindingFlags.Public | BindingFlags.Static);

        foreach (MethodInfo method in methods)
        {
            if (method.Name == "SetDllImportResolver")
                _setDllImportResolverCallback = (SetDllImportResolverDelegate)method.CreateDelegate(typeof(SetDllImportResolverDelegate));
        }
    }
}

static void Main()
{
    _setDllImportResolverCallback(typeof(NativeLibrary).Assembly, (libraryName, assembly, searchPath) =>
    {
        return NativeLibrary.Load("Kernel32");
    });
}

异常触发场景:为System.Private.CoreLib中NativeLibrary类的SetDllImportResolver方法创建委托时抛出异常,自定义委托的结构签名与系统对应委托结构一致,需要修改代码使逻辑正常运行。

异常原因

.NET运行时中,委托类型的匹配判定不看结构签名是否一致,只看运行时类型是否完全相等。
你自定义的DllImportResolver、SetDllImportResolverDelegate属于程序集内单独声明的新类型,和System.Runtime.InteropServices命名空间下系统内置的DllImportResolver委托、SetDllImportResolver方法的参数类型不是同一个运行时类型,因此创建委托时会判定签名不兼容抛出异常。
同时原有代码遍历所有同名方法创建委托的逻辑,也可能因为方法重载匹配到签名错误的重载,进一步触发异常。

修复方案
  • 删除代码中自定义的两个委托类型,直接使用系统内置的DllImportResolver委托(位于System.Runtime.InteropServices命名空间),对应SetDllImportResolver的委托类型可以直接用通用Action<Assembly, DllImportResolver>匹配,无需额外声明。
  • 反射获取方法时通过参数类型精确匹配目标方法,不要遍历所有同名方法盲目创建委托,避免匹配到错误的重载。
  • 如果项目目标框架为.NET Core 3.0、.NET 5及以上版本,NativeLibrary是公开暴露的类型,直接调用原生方法即可,不需要使用反射中转。

修复后的可运行代码:

using System.Reflection;
using System.Runtime.InteropServices;

private const string ReferencedAssemblyName = "System.Private.CoreLib";
private static readonly Action<Assembly, DllImportResolver> _setDllImportResolverCallback;

static Program()
{
    Assembly coreLibAssembly = AppDomain.CurrentDomain
        .GetAssemblies()
        .FirstOrDefault(assembly => assembly.GetName().Name == ReferencedAssemblyName);

    if (coreLibAssembly != null)
    {
        Type nativeLibraryType = coreLibAssembly
            .GetTypes()
            .FirstOrDefault(type => type.Name == "NativeLibrary");
        
        if (nativeLibraryType != null)
        {
            // 按参数类型精确匹配目标方法,避免重载匹配错误
            MethodInfo setResolverMethod = nativeLibraryType.GetMethod(
                "SetDllImportResolver",
                BindingFlags.Public | BindingFlags.Static,
                binder: null,
                new[] { typeof(Assembly), typeof(DllImportResolver) },
                modifiers: null);

            if (setResolverMethod != null)
            {
                _setDllImportResolverCallback = setResolverMethod
                    .CreateDelegate<Action<Assembly, DllImportResolver>>();
            }
        }
    }
}

static void Main()
{
    _setDllImportResolverCallback(typeof(NativeLibrary).Assembly, (libraryName, assembly, searchPath) =>
    {
        return NativeLibrary.Load("Kernel32");
    });
}

补充提示:反射逻辑仅适用于特殊场景下的兼容处理,常规开发直接调用NativeLibrary.SetDllImportResolver(assembly, resolver)即可,不需要编写反射代码。

内容的提问来源于stack exchange,提问作者Redplcs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:00:54