2016-03-24 12 views
5

私はバッファにストリームを読み込み、与えられた構造体にロードするこれらの2つの関数を持っています。これらの構造体関数を汎用化する方法は?

TestStruct1 ReadRecFromStream2(Stream stream) 
    { 
     byte[] buffer = new byte[Marshal.SizeOf(typeof(TestStruct1))]; 
     stream.Read(buffer, 0, 128); 
     GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
     try 
     { 
      return (TestStruct1)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(TestStruct1)); 
     } 
     finally 
     { 
      handle.Free(); 
     } 
    } 

    TestStruct2 ReadRecFromStream(Stream stream) 
    { 
     byte[] buffer = new byte[Marshal.SizeOf(typeof(TestStruct2))]; 
     stream.Read(buffer, 0, 128); 
     GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
     try 
     { 
      return (TestStruct2)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(TestStruct2)); 
     } 
     finally 
     { 
      handle.Free(); 
     } 
    } 

これらを組み合わせて構造体のいずれかを取る汎用関数にしたいのですが、これを行う正しい方法はわかりません。

これは正しい方法ですか?

private T ReadRecFromStream<T>(Stream stream) 
    { 
     byte[] buffer = new byte[Marshal.SizeOf(typeof(T))]; 
     stream.Read(buffer, 0, HeaderSize); 
     GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
     try 
     { 
      return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 
     } 
     finally 
     { 
      handle.Free(); 
     } 
    } 
+3

これはかなりokコードと思われます。 – Gelootn

+0

よろしくお願いいたします。私が作ったジェネリック版は間違っていたが、それがなぜ間違っていたかについては何の洞察も提供してくれなかったという人もいました。私はここで尋ねると思った。ありがとう! – pfinferno

+2

おそらく 'HeaderSize'をパラメータとして渡すべきでしょう... T. – xanatos

答えて

2

たぶん、あなたから変換するために、これらのメソッドを使用することができますし、[]のバイトに:似て働くだろう

T ReadRecFromStream<T>(Stream stream) 
    where T : struct 
{ 
    byte[] buffer = new byte[Marshal.SizeOf(typeof(T))]; 
    stream.Read(buffer, 0, buffer.Length); 
    return buffer.FromBytes<T>() 
} 

読む:

public static unsafe byte[] ToBytes<T>(this T value) 
    where T : struct 
{ 
    var result = new byte[Marshal.SizeOf(typeof(T))]; 
    fixed (byte* b = &result[0]) 
    { 
     var p = new IntPtr(b); 
     Marshal.StructureToPtr(value, p, false); 
    } 

    return result; 
} 

public static unsafe T FromBytes<T>(this byte[] bytes, int startIndex = 0) 
    where T : struct 
{ 
    fixed (byte* b = &bytes[startIndex]) 
    { 
     var p = new IntPtr(b); 
     return (T)Marshal.PtrToStructure(p, typeof(T)); 
    } 
} 

をこれはあなたの方法を使用してに変更することができます。

+0

私はこれが好きです、ありがとう。私はちょっと気付いた、私の構造体のフィールドの数が異なるので、私は構造体の型のどこかで渡す必要がありますか?私の元の2つの関数は 'that struct'型であったからです。 – pfinferno

+0

@pfinferno問題はありません。これらのメソッドに好きな構造体を渡すことができます。構造体の定義方法に関するメタ情報を登録する必要はありません。 genericには、正しいバッファを作成するために必要なすべてのデータが含まれています。たぶん私はあなたを勘違いしています。ごめんなさい。 –

+0

申し訳ありませんが、私は方法に構造を渡す方法について混乱していると思いますか?例えば、 'test'という' TestStruct2'を作りましょう。 'ReadRecFromStream'は' TestStruct2'型なので、 'test = ReadRecFromStream(stream)'を実行します。しかし、ジェネリック関数は起こっていないのですか?私はちょうど自分自身をばかげて混乱させるかもしれない。 – pfinferno

関連する問題