Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a type as parameter to an attribute

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.

like image 640
user703016 Avatar asked Apr 29 '11 08:04

user703016


4 Answers

Use the typeof operator (returns an instance of Type):

[Field(0x7C, typeof(float), 3)]
like image 86
Thomas Levesque Avatar answered Oct 21 '22 04:10

Thomas Levesque


Yes: make the attribute take a Type as a parameter, and then pass e.g. typeof(int).

like image 33
Aasmund Eldhuset Avatar answered Oct 21 '22 04:10

Aasmund Eldhuset


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 };
like image 3
PVitt Avatar answered Oct 21 '22 03:10

PVitt


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
        }
    }
}

like image 1
Cheng Chen Avatar answered Oct 21 '22 03:10

Cheng Chen