将类型作为参数传递给属性

时间:2011-04-29 08:56:02

标签: c# generics custom-attributes

我编写了一种通用的反序列化机制,允许我从C ++应用程序使用的二进制文件格式构造对象。

为了保持简洁和易于更改,我创建了一个扩展Field的{​​{1}}类,由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 }; 然后将从文件中提取数据,在适当的偏移处读取正确的类型和大小。

但是,我发现将类型名称作为字符串传递是丑陋的。

是否可以以更优雅而又简短的方式传递类型,以及如何实现?

谢谢。

4 个答案:

答案 0 :(得分:7)

使用typeof运算符(返回Type的实例):

[Field(0x7C, typeof(float), 3)]

答案 1 :(得分:4)

是:将该属性设为Type作为参数,然后传递,例如typeof(int)

答案 2 :(得分:3)

是的,参数必须是Type类型,然后您可以按如下方式传递类型:

[Field(0x7C, typeof(float), 3)]
public float[] BackgroundLightAngle = { 0.0f, 0.0f, 0.0f };

答案 3 :(得分:1)

我认为您不需要将该类型放在属性的构造函数中,您可以从字段中获取它。参见示例:

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