【问题标题】:Is there a way to force application to load references at runtime?有没有办法强制应用程序在运行时加载引用?
【发布时间】:2016-04-13 10:03:34
【问题描述】:

我不想通过代码动态加载库。

我想做如下的事情:

//first assembly
public void Go()
{
    //second assembly does not loaded yet
    var s = new TestItem(); //at this point second assembly will be loaded before calling the constructor
}

//second assembly
public class TestItem
{
    public TestItem()
    {

    }
}

即我只想在调用程序集中的成员时才加载引用的库。可能吗?如果可能的话 - 我该怎么做?

【问题讨论】:

  • 不要相信如果没有你调用的某种包装类在你第一次调用它时加载 dll 是可能的 - 请参阅shim
  • 如果我理解正确的话,也许托管可扩展性框架 (MEF) 及其延迟加载功能可以为您提供帮助。
  • 程序集动态加载的。但是加载发生的时间比您预期的要早一个阶段——因为系统在编译一个使用来自程序集的类型的方法时需要加载程序集。 (或者当它访问使用依赖类型作为基类或实现接口的类型时)
  • @Damien_The_Unbeliever 是对的。引用程序集不必每次都呈现。它们仅在使用来自其他程序集的类型(字段/属性/方法参数)的类型/方法时加载。
  • @Damien_The_Unbeliever 所以,我的问题的答案是“否”。那么,我可以强制项目在运行时编译引用的程序集吗?

标签: c#


【解决方案1】:

正如 Damien_The_Unbeliever 已经在 cmets 中指出的那样,只要使用其中的类型,就会动态加载程序集。根据使用类型的位置,在加载类型(属性、字段、方法参数 ...)或调用方法(局部变量、静态调用)时会发生这种情况。

在您的示例中,如果您真的想根据条件加载另一个程序集,我建议将其放在另一种方法中。这样,只有在调用 GoDeep() 时才会加载其他程序集。

//first assembly
public void Go()
{
    if (condition)
        GoDeep();
}
[MethodImpl(Met‌​hodImplOptions.NoInlining)]
private void GoDeep()
{
    var s = new TestItem(); //at this point second assembly will be loaded 
}

有趣的事实:这就是FileNotFoundExceptions 不会在应用程序启动时被抛出的原因,但有时可能是几天后,当用户最终点击一个会使用丢失文件的按钮时。

编辑:为了确保该方法未在 Release 中内联,这是为 JIT 添加的。我想补充一点,我根本不会使用这种方法,因为它至少可以说是有风险的,并且可能导致应用程序失败。

【讨论】:

  • 据我了解,Damien 写道,当调用另一个程序集的方法正在编译时,该程序集将被加载。因此,在您的示例中,当 GoDeep 正在编译而不是调用时,将加载另一个程序集。纠正我,如果我不正确
  • 当他说 compiling 时,他指的是 JIT 编译器,它在第一次使用方法时被调用。因此名称 JustInTime 编译器。
  • 这个方法很可能在发布模式下不起作用,因为GoDeep 方法是内联的一个很好的候选者(因此将被完全删除并且调用由它的内容代替)......你可以用[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 装饰GoDeep 方法来防止这种情况发生
  • @Jcl 是的,你是对的。冒昧添加您的建议。
  • 嗯,谢谢,我明白了,我还没有实现编译的全生命周期
猜你喜欢
  • 2011-01-23
  • 2017-09-02
  • 1970-01-01
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 1970-01-01
  • 2013-02-07
  • 2019-07-08
相关资源
最近更新 更多