2012-09-18 3 views
9

List<Tuple<string, Type, object>>をシリアル化しようとしたとき、私は次のエラーメッセージを取得しています:いいえシリアライザは、タイプに対して定義:System.TypeをいるProtobuf-Netのエラーメッセージ:いいえシリアライザはタイプに対して定義:System.Typeを

を私はシリアライズ、両方試してみました上記のコレクション、またはprotoMemberとして定義された同じコレクションを持つクラスのシリアライズ両方とも同じエラーメッセージが表示されます。

これはサポートされていないタイプですか?私はそれがサポートされていると仮定し、私は何か他を見落としたが、多分私は間違っている?これを解決するのに役立つ可能性のあるポインタのための

おかげで...

+0

更新の答えを参照してください。これは後であなたのコメントのために –

答えて

12

編集:Typeシリアル化

サポートはいるProtobufネットはあなたのをシリアル化するためのものであるR580


に含まれていますデータ、あなたの実装ではありません。 Typeは実装の詳細です。厳密に言えば、追加することは非常に難しいことではないでしょう(実装固有の詳細のいくつかはすでにアセンブリ修飾名によってType情報を格納することになります)が、それは重要なシナリオではなく、多くの場合方法はではない何か私はあなたがシリアル化することをお勧めします - プロトコルバッファの全体のポイントは、バージョンの許容差をキーとする任意のプラットフォームでデータを読み込むことができることです。 Typeの情報を格納すると、これらの両方に違反します。

またTypeをシリアライズすることを拒否します(すでにプラットフォーム/バージョン-寛容のすべてのルールを破るおそらくBinaryFormatter除く、)ほとんどシリアライザことにもに留意すべきです。 XmlSerializerDataContractSerializerJavaScriptSerializerなどすべてはこのシナリオの例外を投げます(私はそれらをチェックしました)。さらに

:あなたはDynamicType機能を使用しない限りobjectは、さえ少ないサポート可能です。


ここではTypeに代理を経由して行うことができる方法は次のとおりです。

using ProtoBuf; 
using ProtoBuf.Meta; 
using System; 
using System.Runtime.Serialization; 

static class Program 
{ 
    public static void Main(string[] args) 
    { 
     // register a surrogate for Type 
     RuntimeTypeModel.Default.Add(typeof(Type), false) 
           .SetSurrogate(typeof(TypeSurrogate)); 
     // test it 
     var clone = Serializer.DeepClone(new Foo { Type = typeof(string) }); 
    } 
} 

[ProtoContract] 
class TypeSurrogate 
{ 
    [ProtoMember(1)] 
    public string AssemblyQualifiedName { get; set; } 
    // protobuf-net wants an implicit or explicit operator between the types 
    public static implicit operator Type(TypeSurrogate value) 
    { 
     return value==null ? null : Type.GetType(value.AssemblyQualifiedName); 
    } 
    public static implicit operator TypeSurrogate(Type value) 
    { 
     return value == null ? null : new TypeSurrogate { 
      AssemblyQualifiedName = value.AssemblyQualifiedName }; 
    } 
} 

[DataContract] 
public class Foo 
{ 
    [DataMember(Order=1)] 
    public Type Type { get; set; } 
} 
+0

ありがとうのビルドに含まれています。しかし、そのようなコレクションをシリアライズするにはどうしたらいいですか?バイト配列の転送のみを可能にするメッセージバスを介して送る必要があります。タイプを文字列に変換してから、タイプをオプションに変換していますか?私はあなたにオブジェクト型と合意しました、私はあなたに前に尋ねたと思います、あなたはDynamicType機能を教えてくれました。 –

+0

@Freddy実際には、最も単純なことは '.AssemblyQualifiedName'と' Type.GetType(string) 'を使って' string、string、object'を格納することです。あなたが*本当にエキゾチックなものを手に入れたいのであれば、 'Type'(protobuf-netがサポートしています)用のサロゲート*を追加できます。技術レベルでは、あまりにも多くの痛みを伴うことなく直接サポートすることができますが、バズーカを使用して人々が足に撃ち込むのは簡単です。 –

+0

ポインタのおかげで、本当に感謝します。プラットフォームとバージョンの独立性が望ましい目標であると仮定すれば、ライブラリを保つのが合理的です。私はすでにアセンブリの修飾名を使って型を格納するという点であなたの答えに記述したものを前提としていました。そうしないと、後でデシリアライザが型情報の助けを借りずにそのタスクを処理する方法がわかりません。しかし、私はあなたのソースコードを一切見ていないので、私は完全にオフになるかもしれません。 –

関連する問題