如何强制WPF使用使用程序集强名称的资源URI?哎呀!

Phi*_*hil 18 .net wpf resources xaml strongname

好吧,这真的很烦人,之前我注意到WPF生成的用于加载XAML资源的代码似乎没有使用强名称,因此在需要支持并行版本的WPF程序集的情况下可能会出现问题.

事实证明是这样的,它现在给我带来了问题 - 我有一个插件系统,应该支持插件的并排安装,这些插件的版本号(它们的组装版本)不同.这当然可以由.NET支持,因为即使它们具有相同的DLL文件名,也确定程序集具有不同的标识,只要它们具有强名称并且具有不同的公钥/私钥或具有不同的程序集版本号.

现在,如果我们查看visual studio为windows和usercontrols生成的代码,我们会在自动生成的文件中看到以下内容:

/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
    if (_contentLoaded) {
        return;
    }
    _contentLoaded = true;
    System.Uri resourceLocater = new System.Uri("/Sensormatic.AMK1000.Panel;component/views/servicepanelui.xaml", System.UriKind.Relative);

    #line 1 "..\..\..\Views\ServicePanelUI.xaml"
    System.Windows.Application.LoadComponent(this, resourceLocater);

    #line default
    #line hidden
}
Run Code Online (Sandbox Code Playgroud)

注意创建资源定位符的行 - 它使用的是相对URI,它不指定强名称或包含xaml资源的程序集的版本.

我想也许LoadComponent会检查调用程序集的标识并使用它的公钥和版本细节,或者可能检查包含'this'参数类型的程序集的标识.

看起来情况并非如此 - 如果您有两个具有不同版本号(但文件名相同)的程序集,那么您可以获得一个IOException,其中包含"无法找到资源X"的消息(对于上面的示例"无法找到资源"视图/ servicepanelui的.xaml".

更糟糕的是,我很确定这也意味着具有相同文件名但不同公钥/私钥的程序集(即来自不同的发布者)也会导致此错误.

那么,有谁知道怎么解决这个问题?如何使WPF强名称兼容.

请注意,就我而言,这是一个WPF错误.您不应该仅使用Appdomain隔离来避免这种情况.

小智 5

我遇到了同样的问题,这可能是一个可能的解决方案

每次使用.xaml页面在附加的.cs文件构造函数上创建控件时,在InitializeComponent()调用之前,添加以下行:

contentLoaded = true;
var assemblyName = GetType().Assembly.GetName();
System.Windows.Application.LoadComponent(GetType(), new Uri(
                string.Format("/{0};v{1};component{2}/{3}.xaml",
                assemblyName.Name,
                assemblyName.Version,
                [[[namespace]]],
                type.Name
                ), UriKind.Relative))

其中[[[namespace]]]输入类的完整命名空间,但visual studio项目默认命名空间除外

(注意:连接时打开一个打开的 https://connect.microsoft.com/VisualStudio/feedback/details/668914/xaml-generated-code-uses-resource-uri-without-assembly-strong-name)


Aar*_*ten 5

您可以在项目文件中设置以下内容以更改生成的代码中的URI:

<PropertyGroup>
  <AssemblyVersion>1.0.0.0</AssemblyVersion>
  <AssemblyPublicKeyToken>[YOUR_PUBLIC_KEY_TOKEN]</AssemblyPublicKeyToken>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)


Ken*_*art 3

我倾向于认为这可能是一个错误,或者至少是 XAML 工具中的一个缺陷。也许您应该在Connect上报告它。

我还没有尝试过,但这里有一些潜在的解决方法:

  1. 注入预构建步骤以自动修改 .g.cs 文件以使用指定完整程序集信息的包 URI ( AssemblyShortName[;Version][;PublicKey];component/Path )
  2. 附加到AppDomain.AssemblyResolve以帮助 CLR 找到正确的程序集