我有一个plugin P
延伸和application A
(.NET40)我无法控制。
P程序集(.NET40)有一个shared dependency D
(.NET35)。
P和D都依赖于FSharp.Core,但版本不同:
P
针对FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
编译
D
是针对FSharp.Core, Version=2.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
仅部署了FSharp.Core,Version = 4.4.0.0,我订阅AppDomain.AssemblyResolve以加载已部署的程序集。
当我在我的机器上测试,其中两个FSharp.Core版本都安装在GAC中时,它们最终都被加载了插件。
我的理解是绑定重定向是这里的解决方案但是如何在不访问app.config的情况下完成?
答案 0 :(得分:2)
您可以将D部署为publisher policy程序集。
此方法的好处是客户端目录不需要包含* .config文件来重定向到更新的版本。发布者策略允许程序集的发布者将* .config文件的二进制版本安装到GAC(以及程序集)。这样,CLR就能够在GAC级别执行请求的重定向。
如果您想绕过某个应用的发布商政策,可以使用<publisherPolicy>
元素在应用的* .config文件中指定。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns=“urn:schemas-microsoft-com:asm.v1”>
<publisherPolicy apply="no" />
</assemblyBinding>
</runtime>
</configuration>
答案 1 :(得分:2)
是的,的确如此。如果您正在编写插件,则app.config文件对于重定向程序集是无用的。该插件将首先在用户计算机上的 machine.config 文件中查找,然后在主程序的 *。config 文件中查找。
这是在为SDL Trados 2017编写插件时在插件方案中执行程序集绑定重定向的两步过程-
第一步:在插件本身中使用try-catch语句来查找有关无法加载的程序集的信息。
就我而言,我怀疑创建Google Cloud AutoML客户端所需的少数程序集之一应该归咎于我,因此我在插件首次尝试创建Google Cloud AutoML客户端的位置附近放置了try-catch语句: >
try
{
client = AutoMlClient.Create();
}
catch (Exception err)
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter("C:/Desktop/log.txt", true))
{
file.WriteLine(err.ToString());
}
}
当我检查在错误期间创建的“ log.txt”文件时,发现以下信息:
System.IO.FileNotFoundException: Could not load file or assembly 'Google.Apis.Auth, Version=1.41.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab' or one of its dependencies. The system cannot find the file specified.
所以!很明显,在创建AutoML客户端的过程中,该插件正在尝试查找1.4.1.0.1.0版的Google.Apis.Auth。但是,为了使我的插件正确编译,我必须使用NuGet安装Google.Apis.Auth版本1.42.0.0。因此,需要对程序集绑定进行重定向。
第二步:添加与该特定程序集相关的事件处理程序,该事件处理程序将在加载之前更改其版本/公钥令牌信息。 在程序的最开始-初始化插件的主窗体窗口的地方,我添加了以下代码:
public Main_form()
{
InitializeComponent();
Version V14200 = new Version("1.42.0.0");
RedirectAssembly("Google.Apis.Auth", V14200, "4b01fa6e34db77ab");
}
public static void RedirectAssembly(string assembly_name, Version targetVersion, string publicKeyToken)
{
ResolveEventHandler handler = null;
handler = (sender, args) => {
//gets the name of the assembly being requested by the plugin
var requestedAssembly = new AssemblyName(args.Name);
//if it is not the assembly we are trying to redirect, return null
if (requestedAssembly.Name != assembly_name)
return null;
//if it IS the assembly we are trying to redirect, change it's version and public key token information
requestedAssembly.Version = targetVersion;
requestedAssembly.SetPublicKeyToken(new AssemblyName("x, PublicKeyToken=" + publicKeyToken).GetPublicKeyToken());
requestedAssembly.CultureInfo = CultureInfo.InvariantCulture;
//finally, load the assembly
return Assembly.Load(requestedAssembly);
};
AppDomain.CurrentDomain.AssemblyResolve += handler;
}
因此,基本上,您必须从插件(使用try-catch语句)获取有关哪个程序集无法加载的信息。然后,您必须添加一个事件处理程序,该事件处理程序将在有问题的程序集开始加载时生效。
就我而言,我知道问题出在Google.Apis.Auth上-该插件想加载1.41.1.0版,但我的插件包含1.42.0.0版。当插件开始寻找Google.Apis.Auth(1.41.1.0)时,事件处理程序将介入并更改版本号,因此插件将加载1.42.0.0版。
我从未接受过任何计算机科学或编程方面的正规培训,所以我不知道该解决方案的强大/推荐性,但是它对我有用。