C#学习教程:我可以让我的程序集引用任何版本的另一个程序集吗?分享


我可以让我的程序集引用任何版本的另一个程序集吗?

我如何编写MyClassLibrary ,以便在加载到进程中时,一切都能正常运行,无论用户加载的是哪个版本的ThirdPartyClassLibrary

一种解决方法是在运行时使用AppDomain.AssemblyResolve事件。 只要程序集的分辨率失败,就会触发此消息。 您可以使用它来将不同版本的程序集加载到CLR尝试加载的版本。

我在GitHub上添加了一个非常简单的演示:

https://github.com/danmalcolm/AssemblyResolutionDemo

设置如下:

AssemblyResolve的处理方式如下:

 public static void Initialise() { AppDomain.CurrentDomain.AssemblyResolve += ResolveThirdPartyLibrary; } private static Assembly ResolveThirdPartyLibrary(object sender, ResolveEventArgs args) { // Check that CLR is loading the version of ThirdPartyLibrary referenced by MyLibrary if (args.Name.Equals("ThirdPartyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=fbcbfac3e44fefed")) { try { // Load from application's base directory. Alternative logic might be needed if you need to // load from GAC etc. However, note that calling certain overloads of Assembly.Load will result // in the AssemblyResolve event from firing recursively - see recommendations in // http://msdn.microsoft.com/en-us/library/ff527268.aspx for further info var assembly = Assembly.LoadFrom("ThirdPartyLibrary.dll"); return assembly; } catch (Exception exception) { Console.WriteLine(exception); } } return null; } 

我们需要在加载ThirdPartyLibrary之前绑定到事件,因此需要显式的Initialise方法。

另请注意,事件仅在程序集的分辨率失败时触发。 如果MyClassLibrary(1.0.0.0)引用的ThirdPartyLibrary版本在GAC中可用,那么它将成功加载并且不会触发AssemblyResolve。 然后将使用2个不同的版本。

我在这里certificate可以使用这种机制,我不是说这是一个好主意。 根据您的应用运行环境以及如何设置/安装/维护等,您需要考虑几件事情。

不,您不能使用对ThirdPartyClassLibrary的引用来构建MyClassLibrary,其方式是“只使用运行时可用的任何版本的ThirdPartyClassLibrary.dll”。

构建库时,任何引用的程序集的版本号都包含在程序集清单中。 针对程序集运行ILDASM工具将显示如下内容:

 ... .assembly extern ThirdPartyClassLibrary { ... .ver 1:0:0:0 } ... 

指定了ThirdPartyClassLibrary的名称和版本。 在运行时,CLR将在第一次运行引用它的MyClassLibrary.dll中的指令时尝试加载ThirdPartyClassLibrary.dll。 它将专门针对ThirdPartyClassLibrary.dll的1.0.0.0版本(如果它是一个强命名的程序集,也需要匹配的公钥)。

以下是CLR在运行时如何定位和绑定到程序集的快速概述(完整详细信息,请访问http://msdn.microsoft.com/en-us/library/yx7xezcf(v=vs.110).aspx ):

步骤1 – 通过检查配置文件确定正确的程序集版本 – 我们将返回到下面的内容,但是现在,如果你不这样做,CLR将尝试加载引用程序集中指定的确切版本,所以它将寻找版本1.0.0.0。

步骤2 – 检查程序集名称是否已绑定到之前,如果是,则使用先前加载的程序集。 请注意,此上下文中的“程序集名称”包括名称版本,公钥标记等,而不仅仅是dll文件的名称。

第3步 – 检查全局程序集缓存GAC(仅限强名称程序集)

第4步 – 通过代码库或探测找到程序集 – 本质上CLR在不同的地方查找,试图在某处找到(特定版本)AssemblyB.dll。 如果找不到特定版本,则会发生错误。 它不会自动回退到更早版本或更高版本。

不幸的是,这意味着事情不会“正常工作”并支持您在上面描述的内容。 如果引用MyClassLibrary的应用程序引用了ThirdPartyClassLibrary的更高版本(2.0.0.0),则在解析MyClassLibrary对ThirdPartyClassLibrary的引用时可能会发生一些不好的事情:

您可以做的一件事是使用您的库配置应用程序,以便CLR将对不同版本的ThirdPartyClassLibrary.dll的引用统一为单个版本。 这让我们回到上面概述的程序集绑定过程的第1步 – 我们实际上更改了CLR正在寻找的ThirdPartyClassLibrary的版本。

绑定重定向( http://msdn.microsoft.com/en-us/library/twy1dw1e.aspx )旨在将对程序集的不同版本的引用引导到单个版本。 这些通常在应用程序的配置文件(Web.config,MyApp.exe.config)中定义,但也可以在机器级别(machine.config)进行全局定义。

以下是将所有早期版本的ThirdPartyClassLibrary.dll重定向到版本2.0.0.0的绑定重定向示例:

           

请注意,这可以由Visual Studio 2013自动处理 ,它可以检测引用不同版本的程序集的情况,并为您添加绑定重定向。 NuGet包管理器控制台中还提供了一个Add-BindingRedirect命令。

绑定重定向是一种可能的解决方案,在某些情况下可能是一种实用的选择。 但是,他们也可能会混淆您图书馆的用户。 如果可行,您应该考虑分发不同版本的库,这些版本是根据第三方库的不同版本构建的。

上述就是C#学习教程:我可以让我的程序集引用任何版本的另一个程序集吗?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/960107.html

发表评论

邮箱地址不会被公开。 必填项已用*标注