加载具有不同版本的相同程序集并安装多个 .xaml 实例

Loading same Assembly with different versions and instnatiating multiple .xaml instances

这是对我的问题 的跟进。

我想在不同版本中加载同一个程序集,并从这些程序集中创建多个类型实例。

这是我的资料:

我有一个程序集 asm.dll,其版本(在 AssemblyInfo.cs 内)设置为 1.0.0.0。

然后,我修改了一些代码并将版本增加到 2.0.0.0 并再次构建它作为 asm.dll。

现在,我有 dir1/asm.dll 和 dir2/asm.dll.

我是这样做的:

assembly = Assembly.LoadFile(assemblyFile);

var types = assembly.GetTypes();

Type type = types.First<Type>(t => t.Name.Equals(backboneMemberClass + "Editor"));

MyObject myObject = (MyObject)assembly.CreateInstance("theClassIWantToInstantiate", false, BindingFlags.CreateInstance, null, new object[] { }, null, null);

这是问题所在:

如果我使用 "dir1/asm.dll" 作为 assemblyFile,上面的工作正常:调用 assembly.CreateInstance(...) returns 我请求的实例。

如果我再次使用 "dir2/asm.dll" 它仍然可以正常工作。 Assembly.CreateInstance returns 正确的实例。

但是,如果我再次想创建一个我之前已经创建过的对象的实例(通过调用 Assembly.CreateInstance),我将收到以下异常:

A first chance exception of type 'System.Exception' occurred in PresentationFramework.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll

我正在加载的 class 是一个 .xaml WPF UserControl,异常的 Stacktrace 表示 .xaml.cs 文件中的 InitializeComponent() 正在抛出异常,因为它找不到 .baml 文件。

经过一个星期的折腾和折腾,我终于找到了问题的原因和解决方法。

问题出在自动生成的 *.g.i.cs 文件中,该文件由 UserControlInitializeComponent() 方法调用,如下所示:

此文件生成一个字符串(资源定位器),表示 xaml 组件的路径,如下所示:

现在,如果您有 同一程序集的多个版本 并且两个版本都包含相同的 xaml 文件,WPF 不知道要实例化什么 xaml-file,因为资源定位器只引用程序集的名称而不是它的版本。

这导致 TargetInvocationException,即

{"The component 'MyNamespace.MyUserControl' does not have a resource identified by the URI '/MyAssembly;comoponent/myusercontrol.xaml'"}

如下:

对此的简单(但绝对不是显而易见的)解决方案是将程序集的版本添加到此资源定位器。这可以通过添加 <AssemblyVersion>-tag 修改项目的构建文件来实现,如下所示:

致谢名单: