2016-03-24 7 views
5

मेरे पास इन दो कार्य हैं जो एक बफर में एक स्ट्रीम पढ़ते हैं और इसे दिए गए ढांचे में लोड करते हैं।इन संरचनाओं को सामान्य कैसे बनाएं?

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

मैं structs के दोनों लेने के लिए एक सामान्य समारोह में इन संयोजित करना चाहते हैं, मैं सिर्फ उचित तरीके से यह है कि क्या करना है अनिश्चित हूँ।

क्या यह सही तरीका है?

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

यह बहुत अच्छा कोड लगता है, – Gelootn

+0

ठीक है, धन्यवाद। किसी ने मुझे व्यक्तिगत रूप से बताया कि मैंने जो सामान्य संस्करण बनाया है वह गलत था, लेकिन इस बारे में कोई अंतर्दृष्टि नहीं दी कि यह गलत क्यों था। चित्रित मैं यहां पूछूंगा। धन्यवाद! – pfinferno

+2

शायद आपको 'हेडरसाइज' को पैरामीटर के रूप में पास करना चाहिए ... जब तक यह सभी टी – xanatos

उत्तर

2

हो सकता है कि आप इन तरीकों का उपयोग से कन्वर्ट करने के लिए कर सकते हैं और [] बाइट के लिए: यह आपकी तरीकों का उपयोग करना

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

को बदला जा सकता है:

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

पढ़ें समान काम करेगा।

+0

मुझे यह पसंद है, धन्यवाद। मुझे अभी एहसास हुआ कि, मेरे structs के पास फ़ील्ड की अलग-अलग संख्या है, तो क्या मुझे कहीं भी संरचना के प्रकार में गुजरना होगा? चूंकि मेरे मूल दो कार्य प्रकार 'उस संरचना' के थे। – pfinferno

+0

@pfinferno मुझे समस्या नहीं आती है। आप इन तरीकों से अपनी पसंद की किसी भी संरचना को पारित कर सकते हैं। संरचना को परिभाषित करने के तरीके के बारे में आपको मेटा जानकारी पंजीकृत करने की आवश्यकता नहीं है। जेनेरिक में सही बफर बनाने के लिए आवश्यक सभी डेटा होते हैं। शायद मैं आपको याद करता हूँ। माफ़ कीजिये। –

+0

क्षमा करें, मुझे लगता है कि मैं इस प्रक्रिया में संरचना को पारित करने के तरीके पर उलझन में हूं? उदाहरण के लिए, मान लीजिए कि मैं 'टेस्टस्ट्रक्चर 2' को 'टेस्ट' कहलाता हूं। अभी मैं 'test = ReadRecFromStream (स्ट्रीम) 'करता हूं, क्योंकि' ReadRecFromStream' 'TestStruct2' प्रकार का है। लेकिन जेनेरिक फ़ंक्शन के साथ ऐसा नहीं हो रहा है? मैं सिर्फ बेवकूफ खुद को भ्रमित कर सकता हूं। – pfinferno

संबंधित मुद्दे