19

わかりました、これは本当にイライラします。XAML リソースをロードするために WPF によって生成されたコードが厳密な名前を使用していないように見えるため、WPF アセンブリのサイド バイ サイド バージョンをサポートする必要があるシナリオでは問題になる可能性があることに以前気付きました。

これは事実であることが判明し、現在問題を引き起こしています-バージョン番号(アセンブリバージョン)のみが異なるプラグインのサイドバイサイドインストールをサポートするプラグインシステムがあります。厳密に名前が付けられていて、異なる公開/秘密キーまたは異なるアセンブリ バージョン番号を持っている場合、同じ DLL ファイル名を持っていても、アセンブリは異なる ID を持つと判断されるため、これはもちろん .NET でサポートできます。

ここで、Visual Studio によってウィンドウとユーザー コントロール用に生成されたコードを見ると、自動生成されたファイルに次のように表示されます。

/// <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
}

リソース ロケーターが作成される行に注意してください。これは、厳密な名前または xaml リソースを含むアセンブリのバージョンを指定しない相対 URI を使用しています。

LoadComponent が呼び出し元のアセンブリの ID を確認し、その公開キーとバージョンの詳細を使用するか、「this」パラメーターの型を含むアセンブリの ID を確認する可能性があると思いました。

これは当てはまらないようです。バージョン番号が異なる (ただしファイル名は同じ) 2 つのアセンブリがある場合、「リソース X が見つかりません」というメッセージとともに IOException が発生する可能性があります (上記の例では、「リソース 'views/servicepanelui が見つかりません」 .xaml'.

さらに悪いことに、これは、ファイル名が同じで公開/秘密キーが異なる、つまり異なる発行元からのアセンブリでも、このエラーが発生することを意味すると確信しています。

それで、誰もこれを回避する方法を知っていますか?WPF の厳密な名前に準拠する方法。

私に関する限り、これは WPF のバグです。これを回避するためだけに Appdomain 分離を使用する必要はありません。

4

7 に答える 7

5

私はこれと同じ問題を経験しましたが、これは可能な解決策かもしれません

.xaml ページを使用してコントロールが作成されるたびに、添付された .cs ファイル コンストラクターで、InitializeComponent() 呼び出しの前に、次の行を追加します。

contentLoaded = true;
var assemblyName = GetType().Assembly.GetName();
System.Windows.Application.LoadComponent(GetType(), new Uri(
                string.Format("/{0};v{1};コンポーネント{2}/{3}.xaml",
                アセンブリ名.名前、
                アセンブリ名.バージョン、
                [[[名前空間]]]、
                タイプ.名前
                )、UriKind.Relative))

[[[namespace]]] として、Visual Studio プロジェクトのデフォルトの名前空間を除く、クラスの完全な名前空間を入力します。

(注: https://connect.microsoft.com/VisualStudio/feedback/details/668914/xaml-generated-code-uses-resource-uri-without-assembly-strong-name接続にチェックが入っているオープンがあります)

于 2011-06-14T09:39:06.757 に答える
5

プロジェクト ファイルで次のように設定して、生成されたコードの URI を変更できます。

<PropertyGroup>
  <AssemblyVersion>1.0.0.0</AssemblyVersion>
  <AssemblyPublicKeyToken>[YOUR_PUBLIC_KEY_TOKEN]</AssemblyPublicKeyToken>
</PropertyGroup>
于 2012-05-17T04:48:22.277 に答える
3

これはおそらくバグであるか、少なくとも XAML ツールの欠陥であることに同意する傾向があります。おそらく、 Connectで報告する必要があります。

私は試していませんが、いくつかの潜在的な回避策があります。

  1. 完全なアセンブリ情報 ( AssemblyShortName[;Version][;PublicKey];component/Path )を指定するパック URIを使用するように .g.cs ファイルを自動的に変更するビルド前の手順を挿入します。
  2. AppDomain.AssemblyResolveにアタッチして、CLR が適切なアセンブリを見つけられるようにします
于 2009-09-21T08:22:49.887 に答える
1

私はVS2012でこれに取り組んできました。この環境で Riccardo のソリューションを機能させることができませんでした。彼のコードのこの変種...

_contentLoaded = true;
var assemblyName = GetType().Assembly.GetName();
Application.LoadComponent(this, new Uri(String.Format("/{0};v{1};component/CustomersFrame.xaml", assemblyName.Name, assemblyName.Version), UriKind.Relative));

...「リソースが見つかりません」の問題は解決しましたが、子要素で次のエラーが発生しました。「名前付きオブジェクトを登録できませんでした。このスコープで重複する名前 '検索' を登録することはできません。

Aaron Martenのソリューションは私にとってはうまくいきます。申し訳ありませんが、コメントや賛成票を投じることはできませんが、担当者がいません。

于 2013-04-02T12:38:46.547 に答える
1

Riccardoの回答に基づくこのコードは、VS2010で機能しました。

最初に、XAML コンストラクターから呼び出すことができるローダー メソッドを定義しました。

namespace Utility
{
    public class Utility
    {
        public static void LoadXaml(Object obj)
        {
            var type = obj.GetType();
            var assemblyName = type.Assembly.GetName();
            var uristring = string.Format("/{0};v{1};component/{2}.xaml",
                assemblyName.Name,
                assemblyName.Version,
                type.Name);
            var uri = new Uri(uristring, UriKind.Relative);
            System.Windows.Application.LoadComponent(obj, uri);
        }
    }
}

次に、各 XAML コントロールのコンストラクターで、InitializeComponent() を次のように置き換えました。

        _contentLoaded = true;
        Utility.Utility.LoadXaml(this);
        InitializeComponent();

RelativeSource バインディングの一部が機能しなくなったことに気付きましたが、これを回避することができました。

于 2016-11-16T18:35:45.177 に答える