如何打包位字段

时间:2018-02-06 15:12:53

标签: c# bit-manipulation system.reflection bit-fields

在我的示例中,我想打包位字段并使用单个变量。 我想获得16位PESHeader结构。但我无法弄清楚如何使用反射来访问和打包这些位。如果你给我提供比使用反射更好的方法,那将是非常有帮助的。

我在Bit fields in C#

使用了示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            PESHeader p = new PESHeader();
            PES1Header p1 = new PES1Header();


            p1.a1 = 3;
            p1.a2 = 2;
            p1.a3 = 1;

            p.b1 = p1;
            p.b2.s2 = 1;

            long l = PrimitiveConversion.ToLong(p1);

            long l2 = PrimitiveConversion.ToLong(p);

            for (int i = 63; i >= 0; i--)
            {
                Console.Write(((l & (1l << i)) > 0) ? "1" : "0");
            }

            Console.WriteLine();

            for (int i = 63; i >= 0; i--)
            {
                Console.Write(((l2 & (1l << i)) > 0) ? "1" : "0");
            }

            Console.WriteLine();            
        }
    }
}


[global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed class BitfieldLengthAttribute : Attribute
{
    uint length;

    public BitfieldLengthAttribute(uint length)
    {
        this.length = length;
    }

    public uint Length { get { return length; } }
}

static class PrimitiveConversion
{
    public static long ToLong<T>(T t) where T : struct
    {
        long r = 0;
        int offset = 0;

        // For every field suitably attributed with a BitfieldLength
        foreach (System.Reflection.FieldInfo f in t.GetType().GetFields())
        {
            object[] attrs = f.GetCustomAttributes(typeof(BitfieldLengthAttribute), false);
            if (attrs.Length == 1)
            {
                uint fieldLength = ((BitfieldLengthAttribute)attrs[0]).Length;

                // Calculate a bitmask of the desired length
                long mask = 0;
                for (int i = 0; i < fieldLength; i++)
                    mask |= 1 << i;

                r |= ((UInt32)f.GetValue(t) & mask) << offset;

                offset += (int)fieldLength;
            }

        }
        return r;
    }
}

struct PES1Header
{
    [BitfieldLength(2)]
    public byte a1;
    [BitfieldLength(2)]
    public byte a2;
    [BitfieldLength(4)]
    public byte a3;
};

struct PES2Header
{
    [BitfieldLength(4)]
    public byte s1;
    [BitfieldLength(4)]
    public byte s2;
};

struct PESHeader
{
    public PES1Header b1;
    public PES2Header b2;
};

1 个答案:

答案 0 :(得分:0)

您可以使用an enum with the [Flags] attribute

[Flags]
enum Something
{
    None = 0,
    RequestTimeout = 1 << 0,
    CorruptedResponse = 1 << 2,
    NuclearApocalypse = 1 << 3
}

分配:

Something s = CorruptedResponse | RequestTimeout; // both flags set

检查标志:

if (s.HasFlag(NuclearApocalypse))

您仍然可以使用按位运算来检查多个值。