C#:如何在动态加载的程序集中更改搜索目录中动态加载的程序集的依赖项?

时间:2016-11-09 17:42:56

标签: c# .net

这是令人费解的,但这里有:

为了与另一个应用程序(在一个单独的目录中)集成,我们动态加载其中一个程序集,然后使用Activator从该程序集中实例化一个对象。目标程序集加载正常,但是在创建对象的实例时,它会尝试动态加载一些额外的依赖项并失败,因为它在我们的app目录中找到了它们的更新版本:

var assm = Assembly.LoadFrom("full.path.to.asm"));
var objType = assm.GetType("MyType", true);
var obj = Activator.CreateInstance(objType);

assm加载正常,并获得objType。激活obj时发生异常,因为它依赖于程序集的旧版本(它在目录中有它),但它首先在我们的app目录中找到一个更新的版本并抱怨它是错误的签名。

我首先尝试设置Environment.CurrentDirectory,但它没有任何区别。

1 个答案:

答案 0 :(得分:1)

您需要订阅AppDomain.AssemblyResolve活动。在那里,您可以重定向它以检查其他目录中缺少的程序集。

public static object CreateInstance()
{    
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.AssemblyResolve += MyResolveEventHandler;
    var assm = Assembly.LoadFrom("full.path.to.asm"));
    var objType = assm.GetType("MyType", true);
    var obj = Activator.CreateInstance(objType);
}

private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
    if (args.Name == "SomeAssemblyIntheOtherFolder")
    {
        var path = Path.Combine(Path.GetDirectoryName("full.path.to.asm"), "SomeAssemblyIntheOtherFolder.dll");
        return Assembly.LoadFrom(path);
    }
    return null;

}

更新:第二个选项是在您的应用中添加程序集绑定重定向,这使得另一个应用程序使用您拥有的较新版本的dll而不是编译时使用的版本。

以下是使用库Common.Logging.dll完成的示例,您可以将其放在app.config文件中。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  ...
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" />
        </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

这将导致您的程序中加载的任何程序集在Common.Logging.dll0.0.0.0之间引用任何版本的3.2.0.0库,只使用3.2.0.0而不是他们构建的版本。