2016-03-24 13 views
5

Tôi có hai chức năng này đọc một dòng vào một bộ đệm và tải nó vào cấu trúc đã cho.Làm thế nào để làm cho các hàm cấu trúc này chung chung?

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(); 
     } 
    } 

Tôi muốn kết hợp chúng thành một chức năng chung để thực hiện một trong các cấu trúc, tôi chỉ không chắc chắn cách thích hợp để thực hiện điều này là gì.

Đây có phải là cách chính xác không?

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

mã này có vẻ khá ok, – Gelootn

+0

OK, cảm ơn. Có người nói với tôi trong người rằng phiên bản chung tôi đã làm sai, nhưng không cung cấp bất kỳ cái nhìn sâu sắc về lý do tại sao/làm thế nào nó đã sai. Tôi đoán là tôi sẽ hỏi ở đây. cảm ơn! – pfinferno

+2

Có lẽ bạn nên vượt qua 'HeaderSize' làm tham số ... Trừ khi nó được sửa cho tất cả các phím T. – xanatos

Trả lời

2

lẽ bạn có thể sử dụng những phương pháp để chuyển đổi từ và đến byte []:

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)); 
    } 
} 

Sử dụng này phương pháp của bạn có thể được thay đổi để:

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>() 
} 

đọc sẽ làm việc tương tự.

+0

Tôi thích điều này, cảm ơn. Tôi chỉ nhận ra mặc dù, cấu trúc của tôi có số lượng khác nhau của các lĩnh vực, vì vậy tôi sẽ phải vượt qua trong các loại cấu trúc một nơi nào đó là tốt? Vì hai hàm ban đầu của tôi là kiểu 'struct'. – pfinferno

+0

@pfinferno Tôi không gặp vấn đề gì. Bạn có thể chuyển bất kỳ cấu trúc nào bạn thích cho các phương thức này. Bạn không cần phải đăng ký thông tin meta về cách cấu trúc được định nghĩa. Bản chung chứa tất cả dữ liệu cần thiết để tạo bộ đệm đúng. Có lẽ tôi không hiểu bạn. Lấy làm tiếc. –

+0

Xin lỗi, tôi đoán tôi đang bối rối về cách chuyển cấu trúc cho phương thức? Ví dụ, giả sử tôi tạo một 'TestStruct2' được gọi là' test'. Bây giờ tôi làm 'test = ReadRecFromStream (stream)', vì 'ReadRecFromStream' là kiểu' TestStruct2'. Nhưng với chức năng chung không xảy ra? Tôi có thể chỉ là ngớ ngẩn bối rối bản thân mình. – pfinferno

Các vấn đề liên quan