创建多个.xaml视图

时间:2016-01-27 18:03:40

标签: c# wpf xaml .net-assembly

我想创建名为view.xaml的.xaml UserControl的多个实例,它位于程序集dir1\asm.dlldir2\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);
    }

我收到以下例外:

enter image description here

带有异常详细信息

enter image description here

我能够在view.xaml的InitializeComponent()方法中跟踪到这个位置的问题:

enter image description here

,更具体地说,在InitializeComponent()中:

enter image description here

2 个答案:

答案 0 :(得分:1)

嗯,这很有趣......

两个程序集都具有相同的资源Uri。如果Uri包含版本但是VS似乎没有把它放在那里它会工作。哪一个最后加载(asm1或asm2)似乎能够使用非版本化的Uri而不会崩溃。

如果,而不是: &#34; / ProblemEditor;组件/ problemeditor.xaml&#34;

你有:&#34; / ProblemEditor; v1.0.0.0; component / problemeditor.xaml&#34;和&#34; / ProblemEditor; v2.0.0.0; component / problemeditor.xaml&#34;

然后就不会有问题了。

我为重建您的环境所做的是:

  1. 使用usercontrol(usercontrol1)
  2. 创建一个usercontrol库
  3. 编译并复制dll(已签名的dll)
  4. 更改版本和用户控件(文本块显示&#34;版本2和#34;而不是&#34;版本1和#34;)
  5. 编译并复制dll(已签名的dll)
  6. 然后我:

    1. 使用Reflexil插件解雇Telerik的JustDecompile(您可以从JustDecompile&#39的插件管理器获取它。)
    2. 加载了dll
    3. 在InitializeComponent方法中找到了Uri
    4. 修改了Uri以包含与dll匹配的版本
    5. &#34;另存为&#34;在dll上。由于他们已经签名并且我们只是修改了它们,Reflexil延迟签名但提出删除强名称或用密钥重新签名(当然,你必须提供.snk密钥文件)。我刚刚重新签名,因为我有密钥文件。
    6. 然后你的代码就可以了!作品! WORKS!

      我希望这对你来说是一个可以接受的解决方案。如果有其他人在不破坏dll的情况下解决这个问题,我也有兴趣知道。

答案 1 :(得分:0)

经过一周的痛苦和苦苦挣扎,我终于找到了问题的原因及其解决方案。

问题在于自动生成的*.g.i.cs文件,该文件由InitializeComponent()的{​​{1}}方法调用,如下所示:

enter image description here

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

enter image description here

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

这导致UserControl,说

  

{“组件'MyNamespace.MyUserControl'没有由URI标识的资源'/ MyAssembly; comoponent/myusercontrol.xaml'”}

如下:

enter image description here

这个简单(但绝不是很明显)的解决方案是将程序集的版本添加到此资源定位器。这可以通过添加TargetInvocationException - 标记修改项目的构建文件来实现,如下所示:

enter image description here

对此的信誉转到: