创建多个 .xaml 视图
Creating multiple .xaml Views
我想创建名为 view.xaml
的 .xaml UserControl 的多个实例,它位于程序集 dir1\asm.dll
和 dir2\asm.dll
中,而 asm.dll
是相同的程序集仅在版本号和 view.xaml.
的实现上有所不同
我有以下设置:
public void TestCreation() {
Assembly asm = null;
asm = Assembly.LoadFile("dir1\asm.dll");
CreateView(asm); // works!
asm = Assembly.LoadFile("dir2\asm.dll");
CreateView(asm); // works!
asm = Assembly.LoadFile("dir1\asm.dll");
CreateView(asm); // FAILS!
}
public void CreateView(Assembly assembly)
{
Type type = assembly.GetTypes().First<Type>(t => t.Name.Equals("View"));
UserControl view = (UserControl)assembly.CreateInstance(type.FullName, false, BindingFlags.CreateInstance, null, new object[] { }, null, null);
}
我收到以下异常:
带有异常详细信息
我能够在我的 view.xaml:
的 InitializeComponent() 方法中跟踪到这个位置的问题
更具体地说,在 InitializeComponent() 中:
嗯,这很有趣...
两个程序集具有相同的资源 URI。如果 Uri 包含版本但 VS 似乎没有把它放在那里,它会起作用。最后加载哪个(asm1 或 asm2)似乎能够使用 non-versioned Uri 而不会崩溃。
如果,而不是:
"/ProblemEditor;component/problemeditor.xaml"
您有:“/ProblemEditor;v1.0.0.0;component/problemeditor.xaml”和“/ProblemEditor;v2.0.0.0;component/problemeditor.xaml"
那就没问题了
我为重建您的环境所做的是:
- 使用用户控件 (usercontrol1) 创建用户控件库
- 编译并复制dll(已签名的dll)
- 更改版本和用户控件(文本块显示 "version 2" 而不是 "version 1")
- 编译并复制dll(已签名的dll)
然后我:
- 使用 Reflexil 插件启动了 Telerik 的 JustDecompile(您可以从 JustDecompile 的插件管理器中获取它)。
- 已加载 dll
- 在 InitializeComponent 方法中找到了 Uri
- 修改了 Uri 以包含与 dll 匹配的版本
- 对 dll 做了 "save as"。由于它们已签名,而我们只是修改了它们,Reflexil 延迟对其进行了签名,但提出删除强名称或 re-sign with key(当然,您必须提供 .snk 密钥文件)。我刚刚 re-sign 编辑了它们,因为我有密钥文件。
那么你上面的代码就可以工作了!作品!成功了!
我希望这是您可以接受的解决方案。如果其他人有办法在不破解 dll 的情况下解决这个问题,我也很想知道。
经过一个星期的折腾和折腾,我终于找到了问题的原因和解决方法。
问题出在自动生成的 *.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
我想创建名为 view.xaml
的 .xaml UserControl 的多个实例,它位于程序集 dir1\asm.dll
和 dir2\asm.dll
中,而 asm.dll
是相同的程序集仅在版本号和 view.xaml.
我有以下设置:
public void TestCreation() {
Assembly asm = null;
asm = Assembly.LoadFile("dir1\asm.dll");
CreateView(asm); // works!
asm = Assembly.LoadFile("dir2\asm.dll");
CreateView(asm); // works!
asm = Assembly.LoadFile("dir1\asm.dll");
CreateView(asm); // FAILS!
}
public void CreateView(Assembly assembly)
{
Type type = assembly.GetTypes().First<Type>(t => t.Name.Equals("View"));
UserControl view = (UserControl)assembly.CreateInstance(type.FullName, false, BindingFlags.CreateInstance, null, new object[] { }, null, null);
}
我收到以下异常:
带有异常详细信息
我能够在我的 view.xaml:
的 InitializeComponent() 方法中跟踪到这个位置的问题更具体地说,在 InitializeComponent() 中:
嗯,这很有趣...
两个程序集具有相同的资源 URI。如果 Uri 包含版本但 VS 似乎没有把它放在那里,它会起作用。最后加载哪个(asm1 或 asm2)似乎能够使用 non-versioned Uri 而不会崩溃。
如果,而不是: "/ProblemEditor;component/problemeditor.xaml"
您有:“/ProblemEditor;v1.0.0.0;component/problemeditor.xaml”和“/ProblemEditor;v2.0.0.0;component/problemeditor.xaml"
那就没问题了
我为重建您的环境所做的是:
- 使用用户控件 (usercontrol1) 创建用户控件库
- 编译并复制dll(已签名的dll)
- 更改版本和用户控件(文本块显示 "version 2" 而不是 "version 1")
- 编译并复制dll(已签名的dll)
然后我:
- 使用 Reflexil 插件启动了 Telerik 的 JustDecompile(您可以从 JustDecompile 的插件管理器中获取它)。
- 已加载 dll
- 在 InitializeComponent 方法中找到了 Uri
- 修改了 Uri 以包含与 dll 匹配的版本
- 对 dll 做了 "save as"。由于它们已签名,而我们只是修改了它们,Reflexil 延迟对其进行了签名,但提出删除强名称或 re-sign with key(当然,您必须提供 .snk 密钥文件)。我刚刚 re-sign 编辑了它们,因为我有密钥文件。
那么你上面的代码就可以工作了!作品!成功了!
我希望这是您可以接受的解决方案。如果其他人有办法在不破解 dll 的情况下解决这个问题,我也很想知道。
经过一个星期的折腾和折腾,我终于找到了问题的原因和解决方法。
问题出在自动生成的 *.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