使用相同dll的2个不同版本?
我已经获得了2个预编译的dll:
Common.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f3b12eb6de839f43, processorArchitecture=MSIL Common.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=f3b12eb6de839f43, processorArchitecture=MSIL
API差异示例:
我正在尝试将两者加载到一个项目中,以执行以下操作:
extern alias v10; extern alias v20; private static void UpgradeUser() { // Load old user var userOld = new v10::Common.Data.UserData(); userOld.loadData("user.dat"); // Create new user var userNew = new v20::Common.Data.UserData(); // Copy properties userNew.FirstName = userOld._firstName; userNew.LastName = userOld._lastName; userNew.Age = userOld._age; // Invoke method from v10 and v20 API userOld.version(); userNew.DisplayVersion(); if (userNew.GetUserInfo() != userOld.getInfo()) { throw new Exception("Discrepencies in upgrade "); } Console.WriteLine("Upgrade done!"); }
我已将项目引用和app.config
设置为以下内容。 我也手动将dll复制到我的输出文件夹中,匹配appconfig hrefs
libs\Common.Data.1_0_0_0.dll v10 libs\Common.Data.2_0_0_0.dll v20
我已经成功地建立了。
但是当我尝试运行它时,我得到UserData.loadData
的MissingMethodException
。
我经历过多个stackoverflowpost,msdn和codeproject文章,但似乎无法让它工作。
链路1 , 链路2 , 链路3 , 链路4
认为我错过了一个重要的步骤,但无法弄清楚是什么,并且可以真正使用一些帮助。
[EDIT1]
我已经尝试过单独使用dll,它们可以工作。 (删除了混乱。查看截图的版本历史记录)
[EDIT2]
我尝试了Mukesh Kumar的提议,并将我的app.config更改为:
但它仍然无效。 我现在收到FileNotFoundException
。
[EDIT3]
好吧,我几乎可以肯定不正确,而应该是
。
我尝试从CLI编译:
csc Program.cs /reference:v10=libs/Common.Data.1_0_0_0.dll /reference:v20=libs/Common.Data.2_0_0_0.dll
它工作正常。 我能够同时使用这两个API:
但是当我尝试从Visual Studio构建它时,它会抱怨/引用,即使我已经指定了引用别名:
The extern alias 'v10' was not specified in a /reference option
我已经尝试修改以包含/排除
True
而不起作用。
我找到了这篇文章 ,解决方案是删除并重新添加路径。 使用该解决方案,Visual Studio构建正常,但我回到System.MissingMethodException
。
感觉就像我差不多了,但并不完全。 如何让Visual Studio正确构建?
[Edit4]
我尝试过米格尔的方法,但仍然无法正常工作。
在此尝试中,我已将dll重命名为其原始名称,并将其存储在不同的文件夹中。
然后我更新了app.config以执行bindingRedirect和codebase。
运行它时,我遇到了MissingMethodException
。
我不确定4- Find the and put in False
是什么意思,所以我尝试了 ,
所有组合,以及将
设置为FQN,但这些组合都不起作用。
看看我的第3次编辑,我成功地通过CLI完成编译并运行示例(使用我重命名的dlls + app.config codebase hrefs)。
我现在的问题是,如何配置我的csproj,所以它构建相同。
您需要将dependentAssembly与bindingRedirect一起使用,但您还需要将dll放在不同的文件夹中或使用其他名称保存。 完成此操作后,您需要在app.config中添加以下内容:
使用此代码应编译并运行,但有时VS在编译时删除或覆盖app.config中的代码。 你需要在编译文件夹的配置文件中检查它。 如果成功,您可以编辑.csproj。 为此你必须这样做:
1-卸载受影响的项目
2-右键单击项目
3-单击“编辑项目”
4-找到属性并将其设置为False
5-保存更改并重新加载项目
这对我有用。 在我的项目中,我使用的是两个版本的Automapper。
最后,另一种解决方案是使用AppDomain.CurrentDomain.AssemblyResolve
构建事件并加载特定的dll。
为此,您需要捕获事件:
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); public static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { //debug and check the name if (args.Name == "MyDllName") return Assembly.LoadFrom("c:\\pathdll\midllv1.dll") else if(args.Name ="MyDllName2") return Assembly.LoadFrom("c:\\pathdll\midllv2.dll"); else return Assembly.LoadFrom(""); }
尝试将您的配置详细信息如下所示。
在这里你可以为你提供旧版本和新版本。 你可以按照这篇文章和这个 。
希望这会帮助你。
缺少一个符合我需要的完整答案我决定用AssemblyResolve
方式捐赠我的解决方案,使用两个dll并加载相关文件,使用reflection来解析类型。 对于这个演示,我创建了两个名为MathFuncs
dll,尝试调用它们的Add.add
函数将在两个不同的实现中解析。要查看不同的结果,请在值1和2之间切换版本整数:
public static int version = 1; public static void Main(string[] args) { AppDomain.CurrentDomain.AssemblyResolve += Program.CurrentDomain_AssemblyResolve; version = 1; Type a = Type.GetType("MathFuncs.Add, MathFuncs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); MethodInfo methodInfo = a?.GetMethod("add"); object result = null; if (methodInfo != null) { object[] parametersArray = new object[] {1, 2}; result = methodInfo.Invoke(Activator.CreateInstance(a, null), parametersArray); } if (result != null) { Console.WriteLine((int)result); } else { Console.WriteLine("failed"); } Console.Read(); } public static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { FileInfo fi = null; if (version == 1) { fi = new FileInfo("C:\\Users\\ohbitton\\Desktop\\MathFuncs\\MathFuncs.dll"); } else { fi = new FileInfo("C:\\Users\\ohbitton\\Desktop\\MathFuncs2\\MathFuncs.dll"); } return Assembly.LoadFrom(fi.FullName); }
要获取Type.GetType
的命名空间的完整名称,可以使用powershell:
([system.reflection.assembly]::loadfile("C:\Users\ohbitton\Desktop\MathFuncs\MathFuncs.dll")).FullName