加载具有不同版本的相同程序集并安装多个 .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
文件中,该文件由 UserControl
的 InitializeComponent()
方法调用,如下所示:
此文件生成一个字符串(资源定位器),表示 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 修改项目的构建文件来实现,如下所示:
致谢名单:
- this blog
- this SO thread
这是对我的问题
我想在不同版本中加载同一个程序集,并从这些程序集中创建多个类型实例。
这是我的资料:
我有一个程序集 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
文件中,该文件由 UserControl
的 InitializeComponent()
方法调用,如下所示:
此文件生成一个字符串(资源定位器),表示 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 修改项目的构建文件来实现,如下所示:
致谢名单:
- this blog
- this SO thread