22

WCF サービスで KnownType 属性を使用する必要を回避する一般的に受け入れられている方法はありますか? いろいろ調べたのですが、以下の2つの選択肢があるようです。

  1. データ コントラクト リゾルバー
  2. NetDataContractSerializer

私は、新しい型を追加するたびに KnownType 属性を静的に追加しなければならないのが好きではないので、避けたいと思っています。

使用する必要がある 3 番目のオプションはありますか? もしそうなら、それは何ですか?そうでない場合、上記の 2 つのオプションのどちらが正しい方法ですか?

編集 - メソッドを使用

3番目のオプションは、リフレクションを使用することです

[DataContract]
[KnownType("DerivedTypes")]
public abstract class FooBase
{
    private static Type[] DerivedTypes()
    {
        return typeof(FooBase).GetDerivedTypes(Assembly.GetExecutingAssembly()).ToArray();
    }
}
4

6 に答える 6

1

どこでも属性が気に入らない場合は、構成ファイルを使用できます。

<system.runtime.serialization>
   <dataContractSerializer>
      <declaredTypes>
         <add type = "Contact,Host,Version=1.0.0.0,Culture=neutral,
                                                              PublicKeyToken=null">
            <knownType type = "Customer,MyClassLibrary,Version=1.0.0.0,
                                             Culture=neutral,PublicKeyToken=null"/>
         </add>
      </declaredTypes>
   </dataContractSerializer>
</system.runtime.serialization>
于 2013-04-25T17:22:49.523 に答える
0

カスタム型を一度にすべて抽出し、シリアル化/逆シリアル化中に使用したいと思います。この投稿を読んだ後、このタイプのリストをどこに挿入すればシリアライザ オブジェクトに役立つかを理解するのにしばらく時間がかかりました。答えは簡単でした。このリストは、シリアライザー オブジェクトのコンストラクターの入力引数の 1 つとして使用されます。

1-シリアライゼーションとデシリアライゼーションに2つの静的ジェネリックメソッドを使用しています。これは、他の人が行う方法とほぼ同じである可能性があります。または、少なくともコードと比較することは非常に明確です。

    public static byte[] Serialize<T>(T obj)
    {
        var serializer = new DataContractSerializer(typeof(T), MyGlobalObject.ResolveKnownTypes());
        var stream = new MemoryStream();
        using (var writer =
            XmlDictionaryWriter.CreateBinaryWriter(stream))
        {
            serializer.WriteObject(writer, obj);
        }
        return stream.ToArray();
    }
    public static T Deserialize<T>(byte[] data)
    {
        var serializer = new DataContractSerializer(typeof(T), MyGlobalObject.ResolveKnownTypes());
        using (var stream = new MemoryStream(data))
        using (var reader =
            XmlDictionaryReader.CreateBinaryReader(
                stream, XmlDictionaryReaderQuotas.Max))
        {
            return (T)serializer.ReadObject(reader);
        }
    }

2- DataContractSerializer のコンストラクタに注意してください。そこには 2 番目の引数があります。これは、既知の型をシリアライザー オブジェクトに注入するためのエントリ ポイントです。

3- 自分のアセンブリから自分で定義したすべての型を抽出するために静的メソッドを使用しています。この静的メソッドのコードは次のようになります。

    private static Type[] KnownTypes { get; set; }
    public static Type[] ResolveKnownTypes()
    {
        if (MyGlobalObject.KnownTypes == null)
        {
            List<Type> t = new List<Type>();
            List<AssemblyName> c = System.Reflection.Assembly.GetEntryAssembly().GetReferencedAssemblies().Where(b => b.Name == "DeveloperCode" | b.Name == "Library").ToList();
            foreach (AssemblyName n in c)
            {
                System.Reflection.Assembly a = System.Reflection.Assembly.Load(n);
                t.AddRange(a.GetTypes().ToList());
            }
            MyGlobalObject.KnownTypes = t.ToArray();
        }
        return IOChannel.KnownTypes;
    }

私は WCF に関与していなかったので (ファイル操作にはバイナリ シリアル化のみが必要でした)、私のソリューションは WCF アーキテクチャに正確に対応していない可能性がありますが、どこかからシリアライザー オブジェクトのコンストラクターにアクセスできる必要があります。

于 2016-11-25T14:26:35.670 に答える