【问题标题】:AppDomain.CreateInstance is not following the rulesAppDomain.CreateInstance 不遵守规则
【发布时间】:2010-02-03 19:27:19
【问题描述】:

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

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

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

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

那么,显而易见的问题是,为什么运行时没有找到引用的程序集,正如“运行时如何定位程序集”的第 2 步所暗示的那样?

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

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 找到程序集我的情况是,我试图故意使用Step 2 中定义的功能.如果运行时可以通过第 4 步找到路径,那将正常工作。这是第 2 步不起作用。

谢谢。

【问题讨论】:

    标签: .net reflection createinstance


    【解决方案1】:

    由于程序集被加载到不同的上下文 - LoadFile 上下文中,因此无法解析,而 AppDomain.CurrentDomain.CreateInstance 尝试使用 Load 上下文解析程序集。

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

    那么为什么 CLR 有加载器 首先是上下文?装载机 上下文有助于确保加载顺序 加载程序集时的独立性。 此外,它们还提供了衡量 隔离组件及其 加载时的依赖项 不同的上下文。

    看起来您已经通过订阅AssemblyResolve 事件解决了问题,但您还可以采用其他几种方法,具体取决于您的要求:

    【讨论】:

    • 谢谢。这解决了我的问题。在我看来,在这种情况下,我在上面原始帖子中的“解决方案”实际上是一个不错的解决方案。程序集被加载到 LoadFrom 上下文中,而不是 Load 上下文中。因此,仅从 AssemblyResolve 返回它是一个不错的解决方案,并且可以将其移动到 Load 上下文中。
    • 我完全同意 - AssemblyResolve 是一个非常好的解决方案。 (事实上​​,当您发表评论时,我正在更新我的答案,以便准确地说出这一点。):)
    【解决方案2】:

    这是MSDN的引述

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

    这是一个很棒的article,详细介绍了用于加载程序集的方法如何影响引用解析。

    特别是这篇文章指出 LoadFile 将程序集加载到“两个上下文”中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多