I wrote a somewhat generic deserialization mechanism that allows me to construct objects from a binary file format used by a C++ application.
To keep things clean and easy to change, I made a Field
class that extends Attribute
, is constructed with Field(int offset, string type, int length, int padding)
and is applied to the class attributes I wish to deserialize. This is how it looks like :
[Field(0x04, "int")]
public int ID = 0;
[Field(0x08, "string", 0x48)]
public string Name = "0";
[Field(0x6C, "byte", 3)]
public byte[] Color = { 0, 0, 0 };
[Field(0x70, "int")]
public int BackgroundSoundEffect = 0;
[Field(0x74, "byte", 3)]
public byte[] BackgroundColor = { 0, 0, 0 };
[Field(0x78, "byte", 3)]
public byte[] BackgroundLightPower = { 0, 0, 0 };
[Field(0x7C, "float", 3)]
public float[] BackgroundLightAngle = { 0.0f, 0.0f, 0.0f };
Calling myClass.Decompile(pathToBinaryFile)
will then extract the data from the file, reading the proper types and sizes at the proper offsets.
However, I find that passing the type name as a string is ugly.
Is it possible to pass the type in a more elegant yet short way, and how ?
Thank you.
Use the typeof
operator (returns an instance of Type
):
[Field(0x7C, typeof(float), 3)]
Yes: make the attribute take a Type
as a parameter, and then pass e.g. typeof(int)
.
Yes, the parameter must be of type Type
and then you can pass the type as follows:
[Field(0x7C, typeof(float), 3)]
public float[] BackgroundLightAngle = { 0.0f, 0.0f, 0.0f };
I don't think you need to put the type in the constructor of the attribute, you can get it from the field. See the example:
public class FieldAttribute : Attribute { }
class Data
{
[Field]
public int Num;
[Field]
public string Name;
public decimal NonField;
}
class Deserializer
{
public static void Deserialize(object data)
{
var fields = data.GetType().GetFields();
foreach (var field in fields)
{
Type t = field.FieldType;
FieldAttribute attr = field.GetCustomAttributes(false)
.Where(x => x is FieldAttribute)
.FirstOrDefault() as FieldAttribute;
if (attr == null) return;
//now you have the type and the attribute
//and even the field with its value
}
}
}
来源:https://stackoverflow.com/questions/5830044/passing-a-type-as-parameter-to-an-attribute