【问题标题】:ReflectionTypeLoadException and COM-InteropReflectionTypeLoadException 和 COM 互操作
【发布时间】:2017-11-28 07:17:20
【问题描述】:

我有一个 .Net4 程序集,它公开了一个抽象的基类。在同一个程序集中,我有一些代码反映了文件夹中的所有文件,以构建继承该基类的类列表。这是显着的例程

private JsonTextWriter GetAvailableServices(JsonTextWriter writer, string path)
{
    try
    {            
        writer.WriteStartArray();
        writer = new DirectoryInfo(path).GetFiles(FileFilter)
                                        .Where(f => IsAssembly(f.FullName))
                                        .Select(f => Assembly.LoadFile(Path.Combine(path, f.Name)))
                                        .SelectMany(a => GetLoadableTypes(a))
                                        .Where(p => typeof(ServiceProxy).IsAssignableFrom(p) && !p.IsAbstract)
                                        .Select(a0 => new { Instance = Activator.CreateInstance(a0), ClassName = a0.ToString() })
                                        .Aggregate(writer, (s, v) =>
                                        {
                                            s.WriteStartObject();
                                            s.WritePropertyName(ClassnameLabel);
                                            s.WriteValue(v.ClassName);
                                            s.WritePropertyName(DescriptionLabel);
                                            s.WriteValue(((ServiceProxy)v.Instance).Description);
                                            s.WriteEndObject();
                                            return s;
                                        });                
    }
    catch { Exception ex; }
    finally
    {
        writer.WriteEndArray();                
    }

    return writer;
}

private IEnumerable<Type> GetLoadableTypes(Assembly assembly)
{            
    try
    {
        return assembly.GetTypes();
    }
    catch (ReflectionTypeLoadException e)
    {
        return e.Types.Where(t => t != null);
    }
}

我有一个运行此代码的单元测试,以特定文件夹为目标,一切正常,返回一个继承基类的类列表作为 JSON。

以上代码位于从 COM (VB6) 组件调用的程序集中。如果我现在从 COM 调用相同的代码,针对单元测试所针对的同一文件夹,我会收到反射错误,并且加载器信息报告它无法加载包含上述代码的程序集。这只发生在GetTypes() 调用的GetLoadableTypes 例程中,当我反映包含确实继承基类的类的程序集时。

这听起来几乎像是一个仅在涉及 COM 时才会出现的重入问题。我想我可以将抽象基类放到另一个程序集中,但想知道是否还有其他事情发生。

任何解释或指点显然都非常感激

错误信息:

ReflectionTypeLoadException "无法加载一个或多个 请求的类型。检索 LoaderExceptions 属性以获取更多信息 信息。”

在 LoaderExceptions 中:

"无法加载文件或程序集 'IfxGenDocService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 或其依赖项之一。这 系统找不到指定的文件。":"IfxGenDocService, 版本=1.0.0.0,文化=中性,PublicKeyToken=null"

EDIT1:我做了一些改动,将基类提取到它自己的程序集中,但仍然遇到同样的错误。也许相关的是,我有一个包含 3 个继承基类的类的测试程序集。我得到 3 个 LoaderExceptions(都与上面报告的相同。我假设每个类都有 1 个。

【问题讨论】:

  • 可以添加完整的错误信息吗?
  • 谢谢 .. 刚刚添加

标签: c# reflection com-interop


【解决方案1】:

当程序集被进程锁定时也可能发生这种情况。 Assembly.LoadFile 和 Assmebly.LoadFrom 方法都会锁定程序集,如果您在一个进程中多次调用此方法,则可能会在第二次调用时获得此异常。

为避免锁定,您需要更改此行

    .Select(f => Assembly.LoadFile(Path.Combine(path, f.Name)))

    .Select(f => Assembly.Load(File.ReadAllBytes(Path.Combine(path, f.Name))))

如果所有依赖程序集都位于您正在遍历的目录中,它将起作用,否则您可以检查 System.Reflection.Assembly.LoadFile Locks FileLoading Assembly to Leave Assembly File Unlocked

【讨论】:

    【解决方案2】:

    问题出在这一行

    .Select(f => Assembly.LoadFile(Path.Combine(path, f.Name)))
    

    其实应该是这样的

    .Select(f => Assembly.LoadFrom(Path.Combine(path, f.Name)))
    

    因为 LoadFrom 也会加载依赖项。我假设在运行单元测试时,依赖项必须已经加载。

    【讨论】:

      猜你喜欢
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 2011-07-02
      • 2010-12-14
      • 1970-01-01
      相关资源
      最近更新 更多