Assembly.GetTypes() 由于受保护的抽象方法而抛出 ReflectionTypeLoadException

Assembly.GetTypes() throws ReflectionTypeLoadException because of a protected abstract method

提问人:Sh'dynasty 提问时间:11/16/2023 最后编辑:Sh'dynasty 更新时间:11/16/2023 访问量:51

问:

我正在尝试动态加载程序集并获取其中的类型,但我遇到了这个异常:

System.Reflection.ReflectionTypeLoadException: '无法加载一个或多个请求的类型。程序集“My.Namespace.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中类型为“My.Namespace.Api.Attributes.BasicAuthenticationHandler”的方法“HandleAuthenticateAsync”没有实现。

此类型继承自 abstract 类,该类具有 abstract 方法:Microsoft.AspNetCore.Authentication.AuthenticationHandlerprotected abstract Task<AuthenticateResult> HandleAuthenticateAsync();

我正在从单独的 dotnet 7 应用程序加载这些程序集 - 有没有办法加载这些程序集,以便我可以通过反射看到非公共类型/字段/方法/等?我还可以访问项目本身,因此如果有必要,我可以使用不同的设置来构建它们。

我的代码:

internal class Program
{
    public static void Main(string[] args)
    {
        string path = @"C:\mypublish folder\bin\Debug\net6.0\win-x64";
        AssemblyLoader loader = new AssemblyLoader(path);
        Assembly loadedAssembly = loader.LoadFromAssemblyName(new AssemblyName("My.Namespace.Api"));

        LoadReferencedAssembly(loader, loadedAssembly);
        Type[] types = loadedAssembly.GetTypes();
    }

    private static Dictionary<string, Assembly> loadedAssembliesDict { get; set; } 
        = AppDomain.CurrentDomain.GetAssemblies()
                                 .DistinctBy(x => x.FullName)
                                 .ToDictionary(x => x.FullName);
    private static Dictionary<string, AssemblyName> loadedAssemblyNamesDict { get; set; } 
        = AppDomain.CurrentDomain.GetAssemblies()
                                 .Select(x => x.GetName())
                                 .DistinctBy(x => x.FullName)
                                 .ToDictionary(x => x.FullName);

    private static void LoadReferencedAssembly(AssemblyLoader loader, Assembly assembly)
    {
        if (!loadedAssembliesDict.ContainsKey(assembly.FullName))
            loadedAssembliesDict.Add(assembly.FullName, assembly);

        AssemblyName currentName = assembly.GetName();
        if (!loadedAssemblyNamesDict.ContainsKey(currentName.FullName))
            loadedAssemblyNamesDict.Add(currentName.FullName, currentName);

        foreach (AssemblyName name in assembly.GetReferencedAssemblies())
        {
            if (!loadedAssemblyNamesDict.ContainsKey(name.FullName))
            {
                LoadReferencedAssembly(loader, loader.LoadFromAssemblyName(name));
            }
        }
    }
}


public class AssemblyLoader : AssemblyLoadContext
{
    private string folderPath;

    public AssemblyLoader(string folderPath)
    {
        this.folderPath = folderPath;
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        var deps = DependencyContext.Default;

        var res = deps.CompileLibraries.Where(d => d.Name.Contains(assemblyName.Name)).ToList();
        if (res.Count > 0)
        {
            return Assembly.Load(new AssemblyName(res.First().Name));
        }
        else
        {
            var apiApplicationFileInfo = new FileInfo($"{folderPath}{Path.DirectorySeparatorChar}{assemblyName.Name}.dll");
            if (File.Exists(apiApplicationFileInfo.FullName))
            {
                var asl = new AssemblyLoader(apiApplicationFileInfo.DirectoryName);
                return asl.LoadFromAssemblyPath(apiApplicationFileInfo.FullName);
            }
        }

        return Assembly.Load(assemblyName);
    }
}
C# 反射

评论

1赞 Dai 11/16/2023
向我们显示您的代码,您调用 。Assembly.GetTypes()
0赞 Sh'dynasty 11/16/2023
@Dai - 添加代码
0赞 Dai 11/16/2023
(这是题外话,但你的字典成员应该是字段,而不是可变属性;如果你添加了多线程或并发,那么将它们更改为private static readonlyConcurrentDictionary<K,V>)
0赞 Dai 11/16/2023
该步骤应该是不必要的。.DistinctBy(x => x.FullName)
0赞 Sh'dynasty 11/16/2023
我想我做了一个例外,因为没有重复的键(当然,我现在无法复制)。是的,这非常混乱,我只是想让它工作,然后再让它变得不丑陋。.DistinctBy(x => x.FullName)

答: 暂无答案