Передача типа в качестве параметра в атрибут - PullRequest
8 голосов
/ 29 апреля 2011

Я написал несколько универсальный механизм десериализации, который позволяет мне создавать объекты из двоичного формата файла, используемого приложением C ++.

Чтобы сохранить вещи в чистоте и их легко было изменить, я создал класс Field, которыйextends Attribute, создается с Field(int offset, string type, int length, int padding) и применяется к атрибутам класса, которые я хочу десериализовать.Вот как это выглядит:

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

Вызов myClass.Decompile(pathToBinaryFile) затем извлечет данные из файла, считывая правильные типы и размеры с правильными смещениями.

Однако я нахожучто передача имени типа в виде строки ужасна.

Можно ли передать тип более элегантным, но коротким способом, и как?

Спасибо.

Ответы [ 4 ]

7 голосов
/ 29 апреля 2011

Используйте оператор typeof (возвращает экземпляр Type):

[Field(0x7C, typeof(float), 3)]
4 голосов
/ 29 апреля 2011

Да: заставить атрибут принимать в качестве параметра Type, а затем передать, например, typeof(int).

3 голосов
/ 29 апреля 2011

Да, параметр должен иметь тип Type, и затем вы можете передать тип следующим образом:

[Field(0x7C, typeof(float), 3)]
public float[] BackgroundLightAngle = { 0.0f, 0.0f, 0.0f };
1 голос
/ 29 апреля 2011

Не думаю, что вам нужно помещать тип в конструктор атрибута, вы можете получить его из поля.Смотрите пример:

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

...