ReflectionTypeLoadException 和 COM 互操作

ReflectionTypeLoadException and COM-Interop

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

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);
    }
}

我有一个运行这段代码的单元测试,目标是一个特定的文件夹,它一切正常,返回一个 classes 列表,继承基础 class 作为 JSON。

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

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

非常感谢收到的任何解释或指示

错误信息:

ReflectionTypeLoadException "Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."

并且在 LoaderExceptions 中:

"Could not load file or assembly 'IfxGenDocService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.":"IfxGenDocService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

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

有 1 个

问题出在这一行

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

实际上应该是

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

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

程序集被进程锁定时也可能发生。 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 File and Loading Assembly to Leave Assembly File Unlocked