C# command to get struct offset?
Suppose I have a C# struct like this:
[StructLayout(LayoutKind.Explicit)]
struct IMAGE_DOS_HEADER {
[FieldOffset(60)] public int e_lfanew;
}
Now suppose I read in data from a file, like this:
byte[] data = new byte[4096];
FileStream f = new FileInfo(filename).Open(FileMode.Open, FileAccess.Read);
int n = f.Read(data, 0, 4096);
Now I want to test n
to make sure I've read enough bytes to get the value of e_lfanew
. Is there any way I can get the value 60 (the FieldOffset) without retyping it? I'm looking for something like this:
if (n >= offsetof(IMAGE_DOS_HEADER.e_lfanew) + sizeof(int)) {
...
}
Is there any such command? In my actual code, I have to make several of these tests, and it seems tedious and error-prone to type the numbers in by hand, either by adding up the prior fields in the struct or by copying values out of the FieldOffset a开发者_如何学Gottributes. Is there a better way?
Use Marshal.OffsetOf:
Marshal.OffsetOf(typeof(IMAGE_DOS_HEADER), "e_lfanew")
Yes you can do this using reflection.
FieldOffsetAttribute fieldOffset =
(FieldOffsetAttribute)typeof(IMAGE_DOS_HEADER)
.GetField("e_lfanew")
.GetCustomAttributes(
typeof(FieldOffsetAttribute),
true
)[0];
Console.WriteLine(fieldOffset.Value);
You can even turn this into a nice method:
static int FieldOffset<T>(string fieldName) {
if (typeof(T).IsValueType == false) {
throw new ArgumentOutOfRangeException("T");
}
FieldInfo field = typeof(T).GetField(fieldName);
if (field == null) {
throw new ArgumentOutOfRangeException("fieldName");
}
object[] attributes = field.GetCustomAttributes(
typeof(FieldOffsetAttribute),
true
);
if (attributes.Length == 0) {
throw new ArgumentException();
}
FieldOffsetAttribute fieldOffset = (FieldOffsetAttribute)attributes[0];
return fieldOffset.Value;
}
Usage:
Console.WriteLine(FieldOffset<IMAGE_DOS_HEADER>("e_lfanew"));
Well, you already used a magic number in the structure declaration. Might as well do this:
private const int LfaNewOffset = 60;
[StructLayout(LayoutKind.Explicit)]
struct IMAGE_DOS_HEADER {
[FieldOffset(LfaNewOffset)] public int e_lfanew;
}
...
if (n >= LfaNewOffset + sizeof(int)) {
...
}
精彩评论