属性的默认值=拥有该属性的字段的名称

时间:2011-03-04 17:22:30

标签: c# custom-attributes

我有一个属性,其构造函数有两个字符串。我想使第二个字符串成为可选参数。如果属性的用户未提供第二个参数的值,则其值应等于拥有该属性的字段的名称。我怎么能做到这一点?


这是我的代码:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class WSFieldAttribute : Attribute
{
    private string tableField;
    private string xmlField;

    public WSFieldAttribute(string tableField, string xmlField)
    {
        this.tableField = tableField;
        this.xmlField   = xmlField;
    }

    public object this[DataRow row]
    {
        get { return row[this.tableField]; }
    }

    public object this[XmlWriter writer]
    {
        set
        {
            string toString;

            if (value.GetType() == typeof(string))
                toString = (string)value;
            else if (value.GetType() == typeof(DateTime))
                toString = Utilities.FormatDate((DateTime)value);
            else if (value.GetType() == typeof(DateTime?))
                toString = Utilities.FormatDate((DateTime?)value);
            else
                toString = value.ToString();

            writer.WriteAttributeString(this.xmlField, toString);
        }
    }
}

public class FieldDefinition
{
    private FieldInfo        fieldInfo;
    private WSFieldAttribute wsField;

    public FieldDefinition(FieldInfo fieldInfo)
    {
        object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(WSFieldAttribute), false);

        if (customAttributes.Length != 1)
            throw new InvalidProgramException();

        this.fieldInfo = fieldInfo;
        this.wsField = (WSFieldAttribute)customAttributes[0];
    }

    public object this[DataRow row]
    {
        get { return wsField[row]; }
    }

    public string this[XmlWriter writer]
    {
        set { wsField[writer] = value; }
    }

    public void Read(object element, DataRow row)
    {
        fieldInfo.SetValue(element, this.wsField[row]);
    }

    public void Write(object element, XmlWriter writer)
    {
        this.wsField[writer] = fieldInfo.GetValue(element);
    }
}

public class Row<T> : IXmlSerializable where T : class, new()
{
    private static Type type;
    private static LinkedList<FieldDefinition> fieldDefinitions;

    static Row()
    {
        type = typeof(T);

        FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

        foreach (FieldInfo fieldInfo in fieldInfos)
            fieldDefinitions.AddLast(new FieldDefinition(fieldInfo));
    }

    private T element;

    public Row(DataRow row)
    {
        this.element = new T();

        foreach (FieldDefinition fieldDefinition in fieldDefinitions)
            fieldDefinition.Read(element, row);
    }

    XmlSchema IXmlSerializable.GetSchema() { return null; }

    void IXmlSerializable.ReadXml(XmlReader reader) { throw new NotImplementedException(); }

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        foreach (FieldDefinition fieldDefinition in fieldDefinitions)
            fieldDefinition.Write(element, writer);
    }
}

2 个答案:

答案 0 :(得分:3)

我不相信你可以,我害怕。据我所知,没有办法从属性转到它应用的成员(或其他)。

答案 1 :(得分:2)

虽然您不能这样做,但处理该属性的代码可以检查第二个字符串,如果它为null,则获取应用此属性的字段名称。

您的示例的

简单解决方案:

public class WSField : Attribute {
  // ...
  internal string xmlField;
  public WSField(string tableField, string xmlField = null) {

...

public class FieldDefinition {
  public FieldDefinition(FieldInfo fieldInfo) {
    // ...
    if (this.wsField.xmlField == null) this.wsField.xmlField = fieldInfo.Name;
  }

...