AppDomain.CreateInstance不遵守规则

时间:2010-02-03 19:27:20

标签: .net reflection createinstance

根据How the Runtime Locates Assemblies,第2步是Checking for Previously Referenced Assemblies

但是,在下面的代码中,您可以看到这绝对不会发生。在第一行中,加载了一个程序集(应该使它成为以前所有调用的“先前引用的程序集”。)

但是,稍后当代码调用AppDomain.CurrentDomain.CreateInstance时,会触发AssemblyResolve事件,表明运行时无法找到所请求的程序集。

您可以告诉程序集已加载,因为从AssemblyResolve事件我直接从CurrentDomain.GetAssemblies()返回程序集!!

所以,显而易见的问题是,为什么运行时没有找到引用的程序集作为“运行时如何定位程序集”的第2步意味着什么?

为了运行此示例:创建一个新的控制台应用程序,然后将新的ClassLibrary添加到该解决方案并将其命名为ClassLibrary1。将以下代码粘贴到控制台应用程序的类Program:

class Program
{
    static void Main(string[] args)
    {
        Assembly asmbly = Assembly.LoadFile(Path.GetFullPath(@"..\..\..\ClassLibrary1\bin\Debug\ClassLibrary1.dll"));
        Type firstType = asmbly.GetTypes().First();
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        object myInstance = AppDomain.CurrentDomain.CreateInstance(asmbly.FullName, firstType.FullName);
    }

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        //WHY AM I HERE?
        return AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(p => p.FullName == args.Name);
    }
}

然后使用如下引用添加:

using System.Reflection;
using System.IO;

请注意,我故意将原始路径保留在此处,以便运行时根据Step 4: Locating the Assembly through Codebases or Probing找不到程序集。我的场景是这样的,我试图故意使用{中定义的功能{3}}。如果运行时可以通过步骤4找到路径,那么它将正常工作。步骤2无效。

感谢。

2 个答案:

答案 0 :(得分:3)

它无法解析,因为程序集已加载到不同的上下文 - LoadFile上下文,而AppDomain.CurrentDomain.CreateInstance尝试使用Load上下文解析程序集。

来自Understanding The CLR Binder中的“理解上下文”:

  

那么为什么CLR有加载器   首先是背景?装载机   上下文有助于确保加载顺序   加载程序集时的独立性   此外,他们提供了一个衡量标准   隔离到组件及其组件   加载时的依赖关系   不同的背景。

看起来您已经通过订阅AssemblyResolve事件解决了问题,但根据您的要求,您可能会采取其他几种方法:

答案 1 :(得分:2)

这是MSDN

的引用

使用LoadFile方法加载和检查具有相同标识但位于不同路径的程序集。 LoadFile不会将文件加载到LoadFrom上下文中,也不会像LoadFrom方法那样使用加载路径解析依赖关系。在这种有限的情况下,LoadFile非常有用,因为LoadFrom不能用于加载具有相同标识但路径不同的程序集;它只会加载第一个这样的组件。

这是一个很棒的article,详细介绍了加载程序集的方法如何影响参考分辨率。

特别是本文指出LoadFile将程序集加载到“既不上下文”。