【问题标题】:How can I dynamically reference an assembly that looks for another assembly?如何动态引用查找另一个程序集的程序集?
【发布时间】:2013-09-23 08:56:24
【问题描述】:

为这个狡猾的问题道歉 - 如果有人有更好的建议,很高兴重新措辞。

我正在尝试通过动态调用属于另一个应用程序的程序集来创建一个对象。

以下 PowerShell 代码非常适合我:

[Reflection.Assembly]::LoadFrom("C:\Program Files\Vendor\Product\ProductAPI.dll")
$bobject = new-object ProductAPI.BasicObject    
$bobject.AddName("Some Name") 

我正在努力在 C# 中做同样的事情。根据 StackOverflow 上的其他帖子,我目前有这个:

System.Reflection.Assembly myDllAssembly =
System.Reflection.Assembly.LoadFile("C:\\Program Files\\Vendor\\Product\\ProductAPI.dll");

System.Type BasicObjectType = myDllAssembly.GetType("ProductAPI.BasicObject");

var basicObjectInstance = Activator.CreateInstance(BasicObjectType);

最后一行导致 TargetInvocationException。

{“无法加载文件或程序集 'AnotherObject, Version=1.2.345.0, Culture=neutral, PublicKeyToken=null' 或其依赖项之一。系统找不到指定的文件。”

BasicObject 构造函数似乎正在尝试调用 AnotherObject(来自同一文件夹中的 AnotherObject.dll)但找不到它。

关于如何解决这个问题的任何提示?

【问题讨论】:

  • 我认为您正在加载的 DLL 需要另一个 DLL 才能工作。您可以使用此工具探索 DLL 的依赖关系。 dependencywalker.com
  • 当您找到丢失的 DLL 时。将其复制到您的发布文件夹或修改 Windows PATH 以包含它。
  • 值得使用FUSLOGVW.exeAssembly Binding Log Viewer)检查哪些内容无法加载,它将向您显示哪些内容无法加载(以及 .NET 加载程序正在查找的位置) )。
  • @MathewFoscarini .NET 程序集加载器不直接使用 PATH(现在也使用本机 dll 加载器:或至少不直接使用)。最好考虑 How the Runtime Locates Assemblies。值得注意的是,通过LoadFrom 加载的程序集的位置包括加载任何依赖项时。请参阅我之前的评论:首先要做的是知道找不到什么。
  • 谢谢大家 - 看起来我只是没有意识到可执行文件几乎需要与我要使用的应用程序位于同一文件夹中。

标签: c# powershell reflection assembly-resolution


【解决方案1】:

如果在 the usual places 中找不到依赖程序集,则需要手动指定如何找到它们。

我知道的两种最简单的方法:

  1. 提前手动加载依赖程序集 Assembly.Load.

  2. 处理正在加载的域的 AssemblyResolve 事件 具有附加程序集依赖项的程序集。

两者本质上都要求您提前了解要尝试加载的程序集的依赖关系,但我认为这不是一个大问题。

如果您选择第一个选项,那么还值得研究一下完全加载和reflection-only Load 之间的区别。

如果您更愿意使用2(我推荐),您可以尝试这样的方法,它具有使用嵌套依赖链的额外好处(例如 MyLib.dll 引用 LocalStorage.dll 引用 Raven.Client .dll 引用 NewtonSoft.Json.dll) 并且还会为您提供有关它找不到哪些依赖项的信息:​​

AppDomain.CurrentDomain.AssemblyResolve += (sender,args) => {

    // Change this to wherever the additional dependencies are located    
    var dllPath = @"C:\Program Files\Vendor\Product\lib";

    var assemblyPath = Path.Combine(dllPath,args.Name.Split(',').First() + ".dll");

    if(!File.Exists(assemblyPath))
       throw new ReflectionTypeLoadException(new[] {args.GetType()},
           new[] {new FileNotFoundException(assemblyPath) });

    return Assembly.LoadFrom(assemblyPath);
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    相关资源
    最近更新 更多