加载多个组件版本为多个应用程序域
我的目标是执行某些“一段代码”,即用某些组件,比组件的多个版本。我这样做的方式是通过执行在不同的AppDomain“一段代码”,每一个程序集的版本。加载多个组件版本为多个应用程序域
我能做到这一点,只有当“一段代码”通过反射采用汇编,但我想是有“一段代码”写在强类型的方式。
换句话说,假设我有以下组件:
namespace ClassLibrary1
{
public class Class1
{
internal const string Version = "1.0.0.0";
public string Method1() { return Version; }
}
}
此外,它拥有的AssemblyInfo.cs以下定义:
[assembly: AssemblyVersion(ClassLibrary1.Class1.Version)]
现在让我们假设我有一个“版本”文件夹中我有该组件的多个版本,例如:
/Versions/
├─ /1000/
│ └─ ClassLibrary1.dll
├─ /1001/
│ └─ ClassLibrary1.dll
└─ /1002/
└─ ClassLibrary1.dll
Now to执行“一段代码”我使用下面的控制台应用程序:
class Program
{
static void PieceOfCode(Assembly assembly)
{
Type class1Type = assembly.GetType("ClassLibrary1.Class1");
dynamic class1 = Activator.CreateInstance(class1Type);
string vesion = class1.Method1();
Console.WriteLine(vesion);
}
public sealed class SeparateDomainExecutor : MarshalByRefObject
{
public void Execute(Action<Assembly> action, string assemblyPath)
{
action(Assembly.LoadFrom(assemblyPath));
}
}
static void Main(string[] args)
{
foreach (string file in Directory.EnumerateFiles(@"C:\Versions", "*.dll", SearchOption.AllDirectories))
{
AppDomain domain = AppDomain.CreateDomain("ClassLibrary1 Domain");
var type = typeof(SeparateDomainExecutor);
var runner = (SeparateDomainExecutor)domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
runner.Execute(PieceOfCode, file);
AppDomain.Unload(domain);
}
Console.Read();
}
}
控制台应用程序工作正常,但我想,以取代“PieceOfCode”这反映使用的东西,如下列:
static void PieceOfCode()
{
ClassLibrary1.Class1 class1 = new ClassLibrary1.Class1();
Console.WriteLine(class1.Method1());
}
这可能吗?
我遇到的问题是PieceOfCode会使用某些特定版本的ClassLibrary1(可能是最新版本)编写,我看不到我可以在单独的AppDomain中“覆盖”该版本。 我试过几件事,但我总是FileLoadException结束。
不幸的是,当您在一个静态类型的代码片段中编写ClassLibrary1.Class1
时,您需要一个程序集引用,编译器使用该引用来命名给定版本的类。虽然完全合格的名称(typeof(Class1).AssemblyQualifiedName
)不包含组件的路径或文件名,只是程序集名称和版本的类加载器有进一步的限制,您可能会注意到:
- 它不能从不同的负载2班组件具有相同的名称到同一个命名空间
- 因为路径或文件名是不是程序集引用的一部分,你不能引用2个组件编译时使用相同的强名称
您使用Assembly.LoadFrom(...)
和动态绑定的方式是我能想到的最好的。这就是通常从集成它们的应用程序处理不同版本的Office程序集的方式。
唯一可能的解决方案,我看到的是一段代码分离成一个单独的组件(比如说,MyStaticIntegration.dll)分别编译它针对你的依赖(ClassLibrary1.dll)的每个版本,然后整合MyStaticIntegration的每个版本.dll到您的应用程序中的方式与之前使用ClassLibrary1.dll时的方式相同。
您的应用程序中仍会保留相同的动态墙,但您可以缩小动态使用的界面的范围。
谢谢你的回复,不幸的是你证实了我的担忧。尽管如此,感谢您提供的解决方案。 – bellpatricia
如果它是一个强大的命名程序集并且在加载应用程序之前知道该版本,则可以使用绑定重定向和更改app/web .config文件中的版本 –
“强类型”是“多个版本” 。 .NET通过在类型标识中包含程序集的版本号来实现强类型检查。一个强大的DLL地狱对抗措施,但显然你想通过设计创造地狱。所以你根本不想这样做。 –
是的,确切地说。基本上,我想忽略那个强大的名字 - 地狱保护。 – bellpatricia