الحصول على كثافة العمليات / القصير / بايت تمثيل بنية بايت مع C #

StackOverflow https://stackoverflow.com/questions/225717

سؤال

ونظرا كائن FieldInfo وكائن، ولست بحاجة للحصول على بايت التمثيل الفعلي للحقل. وأنا أعلم أن هذا المجال هو إما int,Int32,uint,short الخ.

وكيف يمكنني الحصول على تمثيل بايت الفعلي؟ سوف BinaryFormatter.Serialize لا يساعد، لأنه سوف تعطيني مزيد من المعلومات من أحتاج (يسجل أيضا كتابة اسم الخ). لا يبدو أن الطبقة Marshal لديها مرافق لاستخدام بايت مجموعة (ولكن ربما أنا في عداد المفقودين شيء).

والشكر

هل كانت مفيدة؟

المحلول

ويمكنك أيضا محاولة كود كما يلي إذا ما كنت فعلا تريد أن نقل الهياكل كما صفيف بايت:

int rawsize = Marshal.SizeOf(value);
byte[] rawdata = new byte[rawsize];
GCHandle handle = GCHandle.Alloc(rawdata, GCHandleType.Pinned);
Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(), false);
handle.Free();

وهذا يحول الكائن نظرا <م> قيمة إلى rawdata صفيف بايت. لقد اتخذت هذا من التعليمات البرمجية كتبت سابقا، والتي قد تحتاج لتكييفه مع الاحتياجات الخاصة بك لجعله فعلا العمل. انا استخدمتها للاتصال مع بعض الأجهزة مع هياكل المعرفة من قبل المستخدم، ولكن يجب أن تعمل لالمدمج في أنواع وكذلك (الهياكل بعد كل شيء، انهم، أليس كذلك؟)

لجعل محاذاة أعضاء بنية بشكل صحيح، استخدام السمة StructLayout لتحديد بايت واحد الانحياز:

[StructLayout(LayoutKind.Sequential, Pack = 1)]

وبعد ذلك استخدام السمة MarshalAs حسب الحاجة للحقول، على سبيل المثال للصفائف مضمنة:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
byte[] _state;

والرمز للحصول على بنية العودة من صفيف بايت شيء من هذا القبيل:

public T GetValue<T>()
{
    GCHandle handle = GCHandle.Alloc(RawValue, GCHandleType.Pinned);
    T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), 
                      typeof(T));
    handle.Free();
    return structure;
}

وبالطبع ستحتاج إلى معرفة النوع الذي تريده لهذا العمل.

لاحظ أن هذا لن التعامل مع endianness لنفسها. في مشروعي، وكانت معظم حقول بايت واحد فقط، لذلك لا يهم، ولكن لعدد قليل من المجالات التي فعلت ذلك، لقد قدمت مجالات القطاع الخاص، وأضاف الممتلكات العامة التي من شأنها أن تأخذ الرعاية من endianness (<لأ href = " http://pobox.com/~skeet/csharp/miscutil "يختلط =" نوفولو noreferrer "> جون السكيت وصلة من تعليق على جوابه قد تساعدك، كتبت بعض الوظائف ذات المنفعة لهذا منذ كنت بحاجة فقط قليل).

وعندما كنت في حاجة الى هذا، أنا خلق فئة رسالة التي من شأنها أن تخزين قيمة الخام (ومن هنا جاء أسلوب GetValue، رمز في الجزء العلوي هو في الواقع الجسم من طريقة SetValue)، وكان بعض الطرق ملاءمة لطيفة للحصول على القيمة المنسقة وما إلى ذلك.

نصائح أخرى

استخدم BitConverter.GetBytes ()

وسيكون لديك أولا لتحويل القيمة إلى انها نوع الأصلي، من استخدام BitConverter للحصول على بايت:

byte[] Bytes;

if (valType == typeof(int))
{
    int intVal = (int) GetFieldValue(....);
    Bytes = BitConverter.GetBytes(intVval);
} 
else if (valType == typeof(long))
{
    int lngVal = (long) GetFieldValue(....);
    Bytes = BitConverter.GetBytes(lngVal);
} else ....

هل يعني نهائي التمثيل في الذاكرة؟ BitConverter.GetBytes (مع الزائد اختيار مناسب عن طريق التأمل) سوف نعود لكم <م> من تمثيل بايت، ولكن ليس بالضرورة ما هو عليه حاليا في الذاكرة.

وربما لو كنت تعطي المزيد من المعلومات حول لماذا تريد هذا، سنكون أكثر قدرة على مساعدتك.

وتحرير: وأود أن أضيف أنه في أي حال من المعقول أستطيع أن أفكر في، BitConverter <م> سوف تعطيك نفس التمثيل كما في الذاكرة - ولكن قد تكون هناك حالات فردية تنطوي على endianness وأبنية ربما غريبة مع مختلف العائمة تمثيل النقطة التي يمكن أن تعطي نتائج غريبة.

وتحرير: وفيما يلي نموذج البرنامج الكامل مما يدل على الطريقة التي قد تذهب عنه:

using System;
using System.Reflection;

public class Test
{
    public int x = 300;

    static void Main()
    {
        Test instance = new Test();
        FieldInfo field = typeof(Test).GetField("x");

        MethodInfo converter = typeof(BitConverter).GetMethod("GetBytes", 
            new Type[] {field.FieldType});

        if (converter == null)
        {
            Console.WriteLine("No BitConverter.GetBytes method found for type "
                + field.FieldType);            
        }
        else
        {
            byte[] bytes = (byte[]) converter.Invoke(null,
                new object[] {field.GetValue(instance) });
            Console.WriteLine("Byte array: {0}", BitConverter.ToString(bytes));
        }        
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top