【问题标题】:Why does Activator.CreateInstance() fail in dynamically loaded assembly?为什么 Activator.CreateInstance() 在动态加载的程序集中失败?
【发布时间】:2015-02-23 22:52:51
【问题描述】:

假设我有一个主机/插件方案:

主持人:

static void Main(string[] args)
{
    var path = @"D:\Plugin.dll";
    var assembly = Assembly.LoadFile(path);
    var type = assembly.GetType("Plugin.K");
    var method = type.GetMethod("Run");
    var instance = Activator.CreateInstance(type);

    method.Invoke(instance, new object[] {});
}

插件:

public class K {
    public void Run() {
        // EXCEPTION THROWN HERE:
        var x = Activator.CreateInstance("Plugin", "Plugin.K");
    }
}

那为什么会抛出下面的异常呢?

An exception of type 'System.IO.FileNotFoundException' occurred in mscorlib.dll but was not handled in user code

Additional information: Could not load file or assembly 'Plugin' or one of its dependencies. The system cannot find the file specified.

程序集不是已经加载到AppDomain中了吗?

【问题讨论】:

  • 可能是路径问题?插件在哪里?
  • 看起来很相似,或者被stackoverflow.com/questions/28684666/…欺骗了
  • 从不使用 LoadFile(),总是使用 LoadFrom()。
  • @MichaelTodd 主机知道插件的路径,因为它调用“var assembly = Assembly.LoadFile(path);”。我想知道为什么框架不知道如何在插件本身中解决它。

标签: c# .net assemblies appdomain


【解决方案1】:

MSDN:

Assembly 类的 LoadFrom 方法在给定文件位置的情况下加载程序集。使用此方法加载程序集使用不同的加载上下文。

推荐的方法是使用 System.Reflection.Assembly 类的静态(在 Visual Basic 中为 Shared)Load 方法。

有关其他选项,请参阅上面的链接。

【讨论】:

    【解决方案2】:

    程序集已由 appdomain 加载。

    在我查看了 Activator.CreateInstance 的源代码之后 我为您找到了解决方案:

    public class K
    {
    
    
        public void Run()
        {
    
            //var f1 = Assembly.GetAssembly(typeof (K)).CreateInstance("Plugin.K");
            //var f2 = Assembly.GetExecutingAssembly().CreateInstance("Plugin.K");
            //var f3 = Activator.CreateInstance(typeof(K));
    
            //won't throw exception
            var x = Activator.CreateInstance(null, "Plugin.K");
    
        }
    }
    

    问题出在 activator.createinstance 内部,当激活器尝试加载程序集名称然后加载程序集时。

    当您将 null 作为程序集名称传递时,激活器将使用:

      assembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
    

    注意:示例 f1-3 也可以。

    【讨论】:

      【解决方案3】:

      在 .net 中调试此开启 Fusion 日志记录

      How to enable assembly bind failure logging (Fusion) in .NET

      如果找不到依赖项失败,那么它将出现在日志中。

      如果没有,它将为您提供有关引发异常的原因的更详细信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-12
        • 2023-03-09
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        • 2017-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多