在我的示例中,我想打包位字段并使用单个变量。 我想获得16位PESHeader结构。但我无法弄清楚如何使用反射来访问和打包这些位。如果你给我提供比使用反射更好的方法,那将是非常有帮助的。
使用了示例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;
};
答案 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))
您仍然可以使用按位运算来检查多个值。