.NET 引用两个不同版本的dll的几种方法
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1. 使用外部别名 (External Aliases)</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">步骤:</a></li><ul class="third_class_ul"><li><a href="#_label3_0_0_0">第一步:添加引用并设置别名</a></li><li><a href="#_label3_0_0_1">第二步:在代码中使用别名</a></li></ul></ul><li><a href="#_label1">2. 使用程序集绑定重定向</a></li><ul class="second_class_ul"></ul><li><a href="#_label2">3. 使用 Assembly.LoadFrom 动态加载</a></li><ul class="second_class_ul"></ul><li><a href="#_label3">4. 创建包装器程序集</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">5. 使用不同的应用程序域</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">最佳实践建议</a></li><ul class="second_class_ul"></ul></ul></div><p>在.NET中引用两个不同版本的DLL是一个常见的需求,特别是在处理依赖冲突或逐步升级时。以下是几种解决方案:</p><p class="maodian"><a name="_label0"></a></p><h2>1. 使用外部别名 (External Aliases)</h2>
<p>这是最常用的方法,允许你在同一个项目中引用两个不同版本的DLL。</p>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>步骤:</h3>
<p class="maodian"><a name="_label3_0_0_0"></a></p><h4>第一步:添加引用并设置别名</h4>
<ol><li>在解决方案资源管理器中添加两个版本的DLL引用</li><li>右键点击每个引用 → 属性</li><li>在属性窗口中设置不同的别名(如 <code>Version1</code> 和 <code>Version2</code>)</li></ol>
<p class="maodian"><a name="_label3_0_0_1"></a></p><h4>第二步:在代码中使用别名</h4>
<div class="jb51code"><pre class="brush:csharp;">// 在文件顶部定义外部别名
extern alias Version1;
extern alias Version2;
using System;
class Program
{
static void Main()
{
// 使用版本1
Version1::MyNamespace.MyClass obj1 = new Version1::MyNamespace.MyClass();
obj1.DoSomething();
// 使用版本2
Version2::MyNamespace.MyClass obj2 = new Version2::MyNamespace.MyClass();
obj2.DoSomething();
// 或者使用全局命名空间限定
var obj3 = new global::MyNamespace.MyClass(); // 使用默认引用
}
}
</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>2. 使用程序集绑定重定向</h2>
<p>在 <code>app.config</code> 或 <code>web.config</code> 中配置绑定重定向:</p>
<div class="jb51code"><pre class="brush:xml;"><configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MyAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
<codeBase version="1.0.0.0" href="lib\v1\MyAssembly.dll" rel="external nofollow" />
<codeBase version="2.0.0.0" href="lib\v2\MyAssembly.dll" rel="external nofollow" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3. 使用 Assembly.LoadFrom 动态加载</h2>
<div class="jb51code"><pre class="brush:csharp;">using System;
using System.Reflection;
class Program
{
static void Main()
{
// 动态加载不同版本的程序集
Assembly version1 = Assembly.LoadFrom(@"path\to\version1\MyAssembly.dll");
Assembly version2 = Assembly.LoadFrom(@"path\to\version2\MyAssembly.dll");
// 通过反射创建实例
dynamic obj1 = version1.CreateInstance("MyNamespace.MyClass");
dynamic obj2 = version2.CreateInstance("MyNamespace.MyClass");
obj1.DoSomething();
obj2.DoSomething();
}
}
</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>4. 创建包装器程序集</h2>
<p>为每个版本创建独立的包装器:</p>
<div class="jb51code"><pre class="brush:csharp;">// Version1Wrapper.cs
public class Version1Wrapper
{
private dynamic _instance;
public Version1Wrapper(string dllPath)
{
var assembly = Assembly.LoadFrom(dllPath);
_instance = assembly.CreateInstance("MyNamespace.MyClass");
}
public void DoSomething() => _instance.DoSomething();
}
// 使用包装器
var wrapperV1 = new Version1Wrapper(@"lib\v1\MyAssembly.dll");
var wrapperV2 = new Version1Wrapper(@"lib\v2\MyAssembly.dll");
</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>5. 使用不同的应用程序域</h2>
<div class="jb51code"><pre class="brush:csharp;">using System;
using System.Reflection;
class Program
{
static void Main()
{
AppDomain domain1 = AppDomain.CreateDomain("Version1Domain");
AppDomain domain2 = AppDomain.CreateDomain("Version2Domain");
// 在不同应用域中加载不同版本
domain1.ExecuteAssembly(@"path\to\version1\app.exe");
domain2.ExecuteAssembly(@"path\to\version2\app.exe");
AppDomain.Unload(domain1);
AppDomain.Unload(domain2);
}
}
</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>最佳实践建议</h2>
<ol><li><strong>优先使用外部别名</strong> - 对于大多数场景这是最直接的方法</li><li><strong>考虑架构设计</strong> - 如果可能,尽量避免同时使用多个版本</li><li><strong>使用接口抽象</strong> - 通过接口隔离不同版本的实现细节</li><li><strong>版本隔离</strong> - 将不同版本放在不同的文件夹中</li><li><strong>充分的测试</strong> - 确保版本间的兼容性和正确性</li></ol>
<p>选择哪种方法取决于你的具体需求、应用程序架构和部署环境。</p>
頁:
[1]