简体   繁体   English

如何动态加载引用同一程序集不同版本的DLL?

[英]How to dynamically load DLLs which reference different versions of same assembly?

We need to run sequentially database updates. 我们需要按顺序运行数据库更新。 Each database update will be its own DLL, and needs to retain a dependency on a specific version of our Domain DLL (the current one at the time the update was written). 每个数据库更新都将是其自己的DLL,并且需要保留对我们域DLL特定版本(编写更新时的当前版本)的依赖性。 For example: 例如:

Cool.Program.Update0001.dll is dependent on Cool.Program.Domain.dll version 1.0.1
Cool.Program.Update0002.dll is dependent on Cool.Program.Domain.dll version 1.0.3
Cool.Program.Update0003.dll is dependent on Cool.Program.Domain.dll version 1.1.6

My plan is to store these DLLs & their dependency DLLs in sub folders as follows: 我的计划是将这些DLL及其依赖性DLL存储在子文件夹中,如下所示:

%APP%\Cool\Program\Updates\0001\Cool.Program.Update0001.dll
%APP%\Cool\Program\Updates\0001\Cool.Program.Domain.dll   (version 1.0.1)

%APP%\Cool\Program\Updates\0002\Cool.Program.Update0002.dll
%APP%\Cool\Program\Updates\0002\Cool.Program.Domain.dll   (version 1.0.3)

%APP%\Cool\Program\Updates\0003\Cool.Program.Update0003.dll
%APP%\Cool\Program\Updates\0003\Cool.Program.Domain.dll   (version 1.1.6)

Then have my main program load & call each Update DLL in sequence, dynamically, using reflection: 然后让我的主程序加载并使用反射按顺序动态调用每个Update DLL:

var path = System.IO.Path.GetDirectoryName(typeof(this).Assembly.Location) + "\\Updates\\" + versionNumber + "\\Cool.Program.Update" + versionNumber + ".dll";
var assembly = System.Reflection.Assembly.LoadFile(path);
var type = assembly.GetTypes().First(x => x.Name == "Updater");
var method = type.GetMethod("DoYourThing");
var result = method.Invoke(null, dbConnection) as string;

Unfortunately, having tested this design and interrogating the version numbers, I find that each UpdateXXXX.dll is working with the LATEST Domain.dll, even though an earlier one is stored in its own subfolder. 不幸的是,在测试了该设计并询问了版本号之后,我发现每个UpdateXXXX.dll都可以与LATEST Domain.dll一起使用,即使较早的版本存储在其自己的子文件夹中。 I assume that they are resolving their dependencies through the GAC, or, defaulting to the dependency already loaded in the main program. 我假设他们正在通过GAC解决它们的依赖关系,或者默认为已经在主程序中加载的依赖关系。 (BTW I see in Visual Studio that it is not possible to force "Specific version" for a project reference and a quick google-fu suggests this isn't straightforward.) (顺便说一句,我在Visual Studio中看到不可能将“特定版本”强制为项目参考,并且快速的Google-fu表示这并不简单。)

My question: 我的问题:

How can I force the Update assembly to resolve its dependency on the Domain dll to its local folder? 如何强制Update程序集将其对Domain dll的依赖关系解析为其本地文件夹?

Or: 要么:

Can I explicitly inject a dependency for a dynamically loaded assembly? 我可以为动态加载的程序集显式注入依赖项吗?

EDIT: I've found an answer, see below. 编辑:我找到了答案,请参阅下文。

I'll answer my own question as I have completed it in the mean time. 在此期间,我将回答我自己的问题。

This code does the trick: 这段代码可以解决问题:

// versionNumber = "0001", "0002" etc

var basePath = Path.GetDirectoryName(typeof(this).Assembly.Location) + "\\Updates\\" + versionNumber + "\\";
var updateAssemblyPath = Path.Combine(basePath, "Cool.Program.Update" + versionNumber + ".dll");

var setup = AppDomain.CurrentDomain.SetupInformation;
setup.ApplicationBase = basePath;
var newDomain = AppDomain.CreateDomain("Updater for " + versionNumber, null, setup);

var obj = (ICanDoSomething)newDomain.CreateInstanceFromAndUnwrap(updateAssemblyPath, "TestDynamicAssemblyLoading.Update"+ versionNumber + ".Class1");
var result = obj.TellMeYourVersionsAndDependencyVersions();
MessageBox.Show(result);

It assumes that the class being used implements a known interface (eg. "ICanDoSomething") and inherits from MarshalByRefObject: 它假定正在使用的类实现了一个已知的接口(例如“ ICanDoSomething”)并继承自MarshalByRefObject:

public class Class1 : MarshalByRefObject, ICanDoSomething
{
    public string TellMeYourVersionsAndDependencyVersions()
    {
        return
            typeof(Class1).Assembly.GetName().Version + "\n\n" +
            "My reference to Domain\n=================\n " + SomeModel.TellMeYourVersionsAndDependencyVersions() + "\n\n" +
            "My reference to Common\n=================\n " + SomeUtility.TellMeYourVersion();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM