C# 在ReflectionOnlyLoadFrom之后无法从程序集获取类型

C# 在ReflectionOnlyLoadFrom之后无法从程序集获取类型,c#,reflection,C#,Reflection,我在网站上查阅了Marius Bancila标题为“将程序集从任何地方加载到新AppDomain”的代码,但我测试了错误,如所附图片所示,目前我不知道如何解决,希望您能提供帮助,谢谢 链接代码 试验 错误 未设置组件分解器 Marius的代码在AssemblyReflectionProxy中有一个缺陷,即如果调用LoadAssembly则未设置程序集解析器,而Reflect则没有设置 根据子应用程序域的创建方式,加载程序集时,它可能只能访问创建期间指定的文件夹。如果需要在别处探测程序集或其依赖

我在网站上查阅了Marius Bancila标题为“将程序集从任何地方加载到新AppDomain”的代码,但我测试了错误,如所附图片所示,目前我不知道如何解决,希望您能提供帮助,谢谢

链接代码

试验

错误

未设置组件分解器 Marius的代码在
AssemblyReflectionProxy
中有一个缺陷,即如果调用
LoadAssembly
则未设置程序集解析器,而
Reflect
则没有设置

根据子应用程序域的创建方式,加载程序集时,它可能只能访问创建期间指定的文件夹。如果需要在别处探测程序集或其依赖项,则需要程序集解析器。当.NET为域查找程序集时,它将按照程序集的
ReflectionOnlyAssemblyResolve
事件中的指定调用您的处理程序。如果未指定,或者冲突解决程序找不到程序集,它将冒泡并引发加载失败异常

我建议您将代码更改为:

public class AssemblyReflectionProxy : MarshalByRefObject
{
  private string _assemblyPath;

  public void LoadAssembly(String assemblyPath)
  {
     try
     {
        _assemblyPath = assemblyPath;
        Assembly.ReflectionOnlyLoadFrom(assemblyPath);
     }
     catch (FileNotFoundException)
     {
        // Continue loading assemblies even if an assembly 
        // cannot be loaded in the new AppDomain.
     }
  }
…致:

public class AssemblyReflectionProxy : MarshalByRefObject
{
  private string _assemblyPath;

  public void LoadAssembly(String assemblyPath)
  {
     try
     {
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve // <---- add me
             += OnReflectionOnlyResolve; 

        _assemblyPath = assemblyPath;
        Assembly.ReflectionOnlyLoadFrom(assemblyPath);
     }
     catch (FileNotFoundException)
     {
        // Continue loading assemblies even if an assembly 
        // cannot be loaded in the new AppDomain.
     }
  }
然后修改OnReflectionOnlyResolve,使其类似于以下内容:

private Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
{
     Assembly loadedAssembly =
         AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
             .FirstOrDefault(
               asm => string.Equals(asm.FullName, args.Name,
                   StringComparison.OrdinalIgnoreCase));

     if (loadedAssembly != null)
     {
        return loadedAssembly;
     }

    foreach (var tryFolder in ResolvePaths)
    {
        var asmName = args.Name.Split(',');
        var assemblyPath = Path.Combine(tryFolder, asmName[0] + ".dll");

        if (!File.Exists(assemblyPath))
            return null;

         return Assembly.ReflectionOnlyLoadFrom(assemblyPath);
    }
}

名字里有什么? 这两篇文章在使用
ReflectionOnlyLoad
时都忽略了指出细节。虽然他的代码是为“代码生成器”编写的,但我不禁想知道,这两篇文章中的“
加载程序集
…到新的AppDomain”可能多少都需要解释

ReflectionOnlyLoad
的目的就是为了反射。如果通过此方法加载程序集,则无法在其中执行任何代码。另外,对于包括我在内的大多数程序集反射器程序员来说,一开始有些令人惊讶的是,调用
GetCustomAttributes
也会这样做(因为它试图“实例化”程序集中的类型)

如果您正在编写自己的插件系统,其中每个插件都有自己的应用程序域,
Assembly
反射和加载方法对于插件系统加载管道的不同阶段非常有用:

  • 首次通过-使用
    ReflectionOnlyLoad
    检查插件是否有效;也许您希望安全地运行一些安全检查,因为在此阶段没有任何插件代码可以运行
  • 第二步-验证插件后,您可以安全地从程序集
    加载
    /
    并执行代码

  • 这回答了你的问题吗?我和你一样编辑过,但还是有错误。不介意,你能帮我编辑一下吗,对不起,我不是。链接代码:@NhuTruong请参阅上面的“添加解决路径的规定”更新抱歉@MickyD,我的问题仍然没有解决。@NhuTruong请注意。因此,这并不是一个解决第三方代码中所有问题的场所。也要注意。我引用。@NhuTruong我鼓励您首先访问Sacha的代码并相应地修改它。另一个代码库更复杂,可能有问题
    public List<string> ResolvePaths { get; set; }
    
    private Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
    {
         Assembly loadedAssembly =
             AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
                 .FirstOrDefault(
                   asm => string.Equals(asm.FullName, args.Name,
                       StringComparison.OrdinalIgnoreCase));
    
         if (loadedAssembly != null)
         {
            return loadedAssembly;
         }
    
        foreach (var tryFolder in ResolvePaths)
        {
            var asmName = args.Name.Split(',');
            var assemblyPath = Path.Combine(tryFolder, asmName[0] + ".dll");
    
            if (!File.Exists(assemblyPath))
                return null;
    
             return Assembly.ReflectionOnlyLoadFrom(assemblyPath);
        }
    }