2

(WYSIWYGの場合、MicrosoftやGoogleの誰かではなく、何がどのように書かれるかを決定することを意味ます OK ...技術的には何も決定しません...数年前にプログラムした誰かが決定しました。私がジャンプしなければならない高さを尋ねることしかできません)

今日は少しばかげていると思いますが、解決策を探すのにすでに2時間を失っています:-(。

今...

私はバイナリプロトコルを持っています。これはCベースなので、マシンのエンディアンが定義されているC構造体を見るようなものであり(幸い、「ローカル」エンディアンと同じです)、さまざまなタイプのサイズが定義され、データ構造のアライメントが定義されています。構造体のレイアウトが定義され、文字列は既知のエンコーディングの文字の固定配列です...すべてが定義されています!unsafe structまた、使用しているときはすべてがC#と非常によく似ており、配列の修飾子の[(LayoutKind.Explicit)]使用についてはあまり気になりません。fixed今度はC#でシリアル化/逆シリアル化する必要があります...周りを見回しましたが、何も見つかりませんでした...何を見逃しましたか?あなたが尋ねる前に、私は知っていますBinaryFormatterが、それは私にとって十分なWYSIWYGではありません...BinaryFormatterそのフォーマット言語を実装しています。ええ、私は知っていますBitConverter(そして、ビッグエンディアン用のコンバーターを実装していないという事実)が、それは「完全な」ソリューションではありません。それは「ベース」の楽器にすぎません。そして、私はBinaryWriter/を知っBinaryReaderていますが、そうでない配列をサポートしていbyte[]ないchar[]ようで、書き込み時に配列を「埋める」ことができないようです(5要素のbyte[]配列があり、それを書き込む必要があります)byte[]使用している形式で必要なため、10要素の配列として...これを行うにはコード行を記述する必要があります)

プランB(ただしプランZでも)は、unsafe structクラスごとにシャドウを作成し、 IWysiwygSerializable2つのメソッド(ReadおよびWrite)を使用してインターフェイスを作成し、すべてのクラスにインターフェイスを実装します(書き込みはにデータを入力unsafe structして出力ストリームに書き込み、読み取りは反対のことをします)(または、を使用せずに、で数十を直接行うこともできますが、BitConverter配列の場合は少し難しくなります)ReadWritestruct

ありがとう!

4

3 に答える 3

3

宣言型のバイナリシリアル化のために、かなり単純ですが拡張可能なフレームワークを作成しました。私は仕事でそれを広範囲に使用しました、そしてそれが途方もない量の努力を節約することをいつも見つけました:

binaryserializer.com

于 2013-03-08T04:50:10.057 に答える
2

BinaryFormatterは使用しないでください。代わりに、BinaryWriterとBinaryReaderを使用して、ディスクに書き込む正確なバイトを、必要な順序でディスクに書き込みます。配列が希望どおりに処理されない場合は、自分で配列をループする必要があります。見栄えを良くするために、ループを実行する拡張メソッドを作成することもできます。

于 2011-06-18T16:16:52.610 に答える
0

(これはおそらく広告と見なすことができますが、「製品」はオープンソースのMITライセンスであり、他の参照される「製品」もオープンソースのMITライセンスです)(私は広告された「製品」の作者であり、他の参照された「製品」)

「良い」解決策がなかったので、私は私のことをしました:-)ライブラリを作成するためだけにライブラリを作成する必要がありました:FluentSerializer。ライブラリを使用して、バイナリデータをシリアル化する方法の「説明」を作成できます。この説明は流暢な表記で書かれています。あなたは(私が書いた他のライブラリ、FluentStatementを通してwhile)あなたの流暢な説明にif、、 ...のようなすべての通常のステートメントを含めることができforます(明らかに流暢な表記を使用しています)。次に、記述は式ツリーとしてコンパイルされ、次に動的メソッドのグループ(Serialize、Deserialize、およびSize(シリアル化されたデータの))としてコンパイルされます。

テストクラス用のシリアライザーの小さなサンプル

/// <summary>
/// 
/// </summary>
public class Serializer : ISerializer<MyClass, EmptyParameters>
{
    #region ISerializer<MyClass,EmptyParameters> Members

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public Expression<Serializer<MyClass, EmptyParameters>> GetSerializer()
    {
        return (op, obj, par) => Statement.Start(fl => fl
            .Serialize(obj.Version)

            // Static objects can be serialized/deserialized.
            .Serialize(MyClass.StaticReadonlyInts1, typeof(FixedLength<>))

            // So can readonly collections.
            .Serialize(obj.ReadonlyInts1, typeof(FixedLength<>))

            // Both array and List<> (and Dictionary<,>, and SortedDictionary<,>, and
            // many other types of collections)
            ////.Serialize(obj.ReadonlyList1)
            .Serialize(obj.ReadonlyList1, typeof(VariableLengthByte<>))

            ////// Readonly fields can be serialized/deserialized.
            ////// Sadly you can't Dump() serializers that replace read only fields
            ////// (replace is the keyword here, readonly int X is a no-no, 
            ////// readonly List<int> X is a yes, readonly int[] X is a yes if it's 
            ////// FixedLength<>.
            ////.Serialize(obj.ReadonlyInt1)

            .Serialize(obj.Bool1)
            .Serialize(obj.Int2)

            // This will be serialized/deserialized only if obj.Version != 0
            // It's only an example of what you can do. You can use the full power of
            // FluentStatement, and remember that if instead of EmptyParameters you
            // had used another class as the parameters, you could have manipulated it
            // through the par object, so par.Version for example.
            .If(obj.Version != 0, fl.Serialize(obj.Int3))

            // This if(s) depend on the operation that is being done
            // (serialization/deserialization/size)
            .If(op == Operation.Serialize, fl.Serialize(obj.Int2))
            .If(op == Operation.Deserialize, fl.Serialize(obj.Int3))

            .Serialize(obj.Short1)

            // Tuples are supported.
            .Serialize(obj.Tuple1)

            // Arrays need to have the length prepended. There are helpers for this.
            // The default helper can be specified in the Serializer<T> constructor and
            // will be used if the field serializer isn't specified.
            ////.Serialize(obj.Ints1)

            // Or you can specify it:
            .Serialize(obj.Ints2, typeof(VariableLengthByte<>))
            .Serialize(obj.Ints3, typeof(VariableLengthByte<int[]>))

            // Nullable types are supported
            .Serialize(obj.NullableInt1, typeof(Nullable<int>))
            ////.Serialize(obj.NullableInt2)

            // But note that you could even use the Optional<> with value types,
            // usefull for example if you have to use a modifier that is a class
            // (like VariableLengthInt32 for example)
            .Serialize(obj.NullableInt1, typeof(Optional<int>))
            .Serialize(obj.NullableInt2, typeof(Optional<>))

            // So are "optional" objects (fields that can be null)
            // (Note that here if we wanted to specify the helper, we would have
            // to use typeof(Optional<VariableLengthByte<int>>)
            .Serialize(obj.OptionalInts1, typeof(Optional<VariableLengthInt32<int[]>>))
            .Serialize(obj.OptionalInts2, typeof(Optional<>))
            .Serialize(obj.OptionalList1, typeof(Optional<VariableLengthInt32<List<int>>>))
            .Serialize(obj.OptionalList2, typeof(Optional<>))

            // You can serialize a DateTime as the full .NET value
            .Serialize(obj.DateTime1)

            // Or, for example, as an Unix datetime (32 or 64 bits)
            .Serialize(obj.DateTime2, typeof(UnixDateTime<int>))

            .Serialize(obj.Float1)
            .Serialize(obj.Double1)
            .Serialize(obj.Decimal1)
            .Serialize(obj.TimeSpan1)

            // For strings it's a little more complex. There are too many combinations 
            // of possible formats (encoding x string length * (use char or byte length))
            // At this time there isn't any helper for C strings (null terminated strings).
            // You have to "manually" register you string formats.
            .Serialize(obj.String1, typeof(Program.MyUtf8VariableLengthInt32String))
            .Serialize(obj.String2, typeof(Program.MyAsciiVariableLengthInt32String))
            .Serialize(obj.String3, typeof(Program.MyUnicodeVariableLengthInt32String))

            // Chain serializing the base class can be done in this way
            .Serialize(obj, typeof(MySimpleClass))

            // This is only to make it easy to add new serialization fields. The last ) is
            // "attached" to the .Empty and doesn't need to be moved.
            .Empty());
    }

    #endregion
}

明らかに、このライブラリは、大量のデータをシリアル化/逆シリアル化する必要がある場合にのみ有効です。シリアル化/逆シリアル化するオブジェクトが1つしかない場合は、おそらくBinaryReader/BinaryWriterで十分です(元の質問で私が提案し、彼の回答でFantiusが提案したように)。

于 2012-09-01T13:54:35.617 に答える