3

クライアントとサーバーで共有エンティティを使用する既存のWCFnet.tcpプロジェクトのシリアライザーを変更しようとしています。protobuf-net(V2480)を理解するのに苦労しています。ここのグラフは、プライベートメンバーをシリアル化できると言っていますが、それを行うためのドキュメントが見つかりません。属性なしで可能ですか?ここで説明されているように、グラフモード(参照として)を有効にするにはどうすればよいですか?

それは私の変更されたアイテムフラグをトリガーするprotobufの問題を解決しますか?たとえば、私はクラスを持っています

 public enum FirstEnum
{ 
    First = 0,
    Second,
    Third
}
public enum AnotherEnum
{ 
    AE1 = 0,
    AE2,
    AE3
}
[Serializable()]
public class SomeClass
{
    public int SomeClassId { get; set; }
    public FirstEnum FEnum { get; set; }
    public AnotherEnum AEnum { get; set; }
    string thing;
    public string Thing
    {
        get{return thing;}
        set
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentNullException("Thing");

            thing = value;
        }
    }

    private decimal firstAmount;
    public decimal FirstAmount 
    { 
        get{return firstAmount;} 
        set
        {
            if (value != firstAmount)
            {
                firstAmount = value;
                changedItems.Add("FirstAmount changed");
            }
        }
    }
    private decimal secondAmount;
    public decimal SecondAmount
    {
        get { return secondAmount; }
        set
        {
            if (value != secondAmount)
            {
                secondAmount = value;
                changedItems.Add("SecondAmount changed");
            }
        }
    }
    public decimal ThirdAmount { get { return SecondAmount - FirstAmount; } }
    public DateTime? SomeDate { get; set; }

    private List<string> changedItems = new List<string>();
    public List<string> ChangedItems
    {
        get { return changedItems; }
    }
public int PrivateSet { get; private set; }
    public SomeClass() { }

    public SomeClass(decimal first, decimal second)
    {
        FirstAmount = first;
        SecondAmount = second;
    }

    public void ClearChangedItems()
    {
        changedItems.Clear();
    }

(1000アイテム)で逆シリアル化すると

 var model = CreateModel();
 items = (List<SomeClass>)model.Deserialize(returnStream, null, typeof(List<SomeClass>));

2012-04-06 09:14:28.1222 | DEBUG | ProtobufTEsts.Form1 | ProtoBuf変更されたアイテムの数:1000

BinaryForrmatterを使用

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
items = (List<SomeClass>)binaryFormatter.Deserialize(returnStream);

2012-04-06 09:14:28.1662 | DEBUG | ProtobufTEsts.Form1 | BinaryFormatter変更されたアイテムの数:0

protobufをbinaryFormatterのように動作させながら、protobufのパフォーマンスを維持する方法はありますか?

プライベートシリアル化を許可する方法、これは失敗します

 public static TypeModel CreateModel()
    {
        RuntimeTypeModel model = TypeModel.Create();
        ///var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false);
        model.Add(typeof(SomeClass), false)
            .Add(1, "SomeClassId")
            .Add(2, "FEnum")
            .Add(3, "AEnum")
            .Add(4, "Thing")
            .Add(5, "FirstAmount")
            .Add(6, "SecondAmount")
            .Add(7, "SomeDate")
            .Add(8, "PrivateSet");
        TypeModel compiled = model.Compile();
        return compiled;
    }
4

2 に答える 2

2

ああ、私は今問題を理解しています。この行には問題があります。

TypeModel compiled = model.Compile();
return compiled;

Compile()を使用すると、アセンブリの通常のルール、特にメンバーのアクセス可能性に従わなければならない正式なアセンブリ(メモリ内)が作成されます。これは、プライベートサーターにアクセスできないことを意味します。

代わりに、以下を使用してください。

model.CompileInPlace();
return model;

これは部分的なコンパイルを実行しますが、DynamicMethodを引き続き使用します。この生意気な小さな生き物には、アクセシビリティルールを通り抜けるオプションがあり(リフレクションのように)、プライベートセッターを引き続き使用できます。

モデルは必要に応じてインプレースで(より詳細なレベルで)コンパイルされるため、CompileInPlaceのこの呼び出しは厳密には必要ありませんが、すべてを事前に行うのに役立ちます。

完全を期すために、追加のCompile(string、string)オーバーロードを使用して、ディスク上に個別のシリアル化dllを生成できます。これは、実行時にメタプログラミングなしで参照および使用できます。

于 2012-04-07T09:36:41.333 に答える
0

はい、protobuf-netはプライベートフィールドをシリアル化でき、属性なしでシリアル化できます。私はPCを使用していないので、調整が必要な場合があります。

var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false);
// for each field in a known order
metaType.Add(fieldName, someUniqueTag);

属性駆動型の使用法には、意図した使用法に合わせて自動的に構成するImplicitFields.AllFieldsもありますが、MetaTypeにImplicitFieldsヘルパーメソッドをまだ追加していません。それをリストに追加します!

注:タグ(=フィールド)番号はprotobufにとって重要であり、逆シリアル化するときに同じ番号マッピングを再現できる必要があります。

検討したいもう1つのオプションは、(逆)シリアル化コールバックです。これにより、現在シリアル化/逆シリアル化されていることを知ることができます(メソッドが呼び出される前/後を介して)。これは、逆シリアル化などの間隔の副作用を無効にする別の方法である可能性があります。

于 2012-04-06T16:58:53.777 に答える