8

プロジェクトにはいくつかのセットアップ クラスがあり、いくつかの .config ファイルから XmlSerializer でシリアル化/逆シリアル化されます。これらのセットアップ クラスの一部には、次のようなサブセットアップのコレクションがあります。

using System;
using System.Collections.ObjectModel;
using System.Xml.Serialization;

namespace Datev.Framework.Shared.Actions.Setup
{
    [Serializable]
    [XmlSerializerAssembly]
    [XmlRoot("setup")]
    public class SetupXml
    {
        public SetupXml()
        {
            SubSetups = new Collection<SubSetupXml>();
        }

        [XmlArray("subSetups")]
        [XmlArrayItem("subSetup")]
        public Collection<SubSetupXml> SubSetups { get; private set; }
    }

    [Serializable]
    public class SubSetupXml
    {
        [XmlElement("someValue")]
        public string SomeValue { get; set; }
    }
}

属性 [XmlSerializerAssembly] を使用して、セットアップの読み取りと書き込みのパフォーマンスを最適化しています。そして、ここに私の問題があります:コレクションを使用して、CA-警告「配列を使用しないでください」を回避しています。SubSetups のセッターを公開すると、CA-Warning CA2227「コレクションのセッターを公開しないでください」が表示されます。プロパティ SubSetups のセッターをプライベートにすると (コード サンプルのように)、生成されたシリアライザーでエラーが発生します。メソッド "GenerateSerializer" (私たちのツールで呼び出されます) コードには次のような行があります。

if (o.SubSetups == null) o.SubSetups = new Collection<SubSetupXml>();

セッターをプライベートにすると、シリアライザーのビルド中に CS0200 "プロパティ サブセットアップを割り当てることができません" が表示されます。CA警告を抑制せずに、生成されたシリアライザーで正しいセットアップを行う方法を知っている人はいますか?

4

6 に答える 6

5

「正しい」セットアップはコンテキストに大きく依存します。簡単なアイデア: ロジックを "GenerateSerializer" からプロパティ ゲッターに移動するとどうなりますか? それは受け入れられるでしょうか?

[XmlArray("subSetups")]
[XmlArrayItem("subSetup")]
public Collection<SubSetupXml> SubSetups { 
   get {
      // subSetups needs to be a backing (private) field... is this a problem?
      if (this.subSetups == null) this.subSetups = new Collection<SubSetupXml>();
   }
   private set; 
}

このように、「GenerateSerializer」ではコレクションを取得するだけです。コレクションがまだ作成されていない場合は、クラスの外で作成する必要なく、getter 内に配置されます。単なるアイデアです。適用できない場合はお知らせください。

于 2013-01-30T11:11:43.960 に答える
3

次のようなものがあります。

    public class SetupXml
    {
        public SetupXml()
        {
            SubSetups = new Collection<SubSetupXml>();
        }

        [XmlIgnore]
        public Collection<SubSetupXml> SubSetups { get; private set; }

        [EditorBrowsable(EditorBrowsableState.Never)]
        [GeneratedCodeAttribute("Whatever", "1.0.0.0")]
        [XmlArray("subSetups")]
        [XmlArrayItem("subSetup")]          
        public SubSetupXml[] SerializationSubSetups
        {
            get
            {
                return SubSetups.ToArray();
            }
            get
            {
                SubSetups = new SubSetups();
                if (value != null)
                {
                    foreach(SubSetupXml ssx in value)
                    {
                        SubSetups.Add(ssx);
                    }
                }
            }
        }
    }

完全ではありませんが、EditorBrowsable属性により、開発者が (別のアセンブリから) このライブラリを使用して、Intellisense/オートコンプリート ツールによって表示されるのを防ぐことができます。また、GeneratedCode 属性により、CA の警告が防止されます。

于 2013-01-31T15:00:00.543 に答える
3

あなたはすでにこの記事を参照していると思いますか? http://msdn.microsoft.com/en-us/library/ms182327.aspx

これは、その記事の重要な注意事項として印象に残っています。「バイナリ シリアル化と XML シリアル化の両方が、コレクションである読み取り専用プロパティをサポートしています。System.Xml.Serialization.XmlSerializer クラスには、ICollection と System.Collections.IEnumerable を実装する型に対して特定の要件があります。シリアル化できるようにします。」

それに加えて、.Clear() と .AddRange() のアプローチを使用してさらに進歩させることができる場合があります。

于 2013-02-01T17:32:44.847 に答える
3

状況が見た目と同じくらい簡単な場合は、コンストラクター(o.SubSetups == null)に行があるため (つまり、もちろん ifの型)かどうかを確認する必要はありません。メソッドからそのステートメントを取り除き、setter を非公開にすれば、問題ないはずです。言及していない、それをいじる他の方法がない限り、プロパティを使用する方法はありません...SubSetups = new Collection<SubSetupXml>();SetupXml()oSetupXmlifGenerateSerializerSubSetupsnull

于 2013-01-30T15:32:10.110 に答える
3

IXmlSerializable インターフェイスの実装を試すことができます。もう少し作業が必要ですが、シリアライゼーションを細かく制御でき、あなたの場合はプライベート クラス変数にアクセスできます。ReadXml メソッドでは、コレクションのインスタンスを作成してインスタンス化し、ソース xml の各ノードを反復処理して、値を解析するだけです。

于 2013-02-02T20:20:51.660 に答える
3

SubSetups のタイプを に変更するIEnumerableと、コード分析の警告が表示されなくなりますが、これが適切かどうかはわかりません。

    [XmlArray("subSetups")]
    [XmlArrayItem("subSetup")]
    public IEnumerable<SubSetupXml> SubSetups { get; set; }
于 2013-01-30T18:29:11.267 に答える