我可以在不使用其名称的情况下获取属性的PropertyInfo吗?

时间:2014-03-26 15:04:20

标签: c# reflection

我有一个具有属性的类,并且该属性具有attribute,并且在该属性的get{}set{}内,我想要访问该属性。

有没有办法这样做而不必将属性的名称引用为string?这有用吗?

class MyClass
{
    [DefaultValue("This is my default")]
    public string MyProperty
    {
        get
        {
            string value = this.db.getMyProperty();
            if (value == null)
            {
                var myPropertyInfo = this.GetType().GetProperty("MyProperty");
                var myAttributeInfo = myPropertyInfo.GetCustomAttribute(
                    typeof (DefaultValueAttribute)) as DefaultValueAttribute;
                if (myAttributeInfo != null)
                    value = myAttributeInfo.defaultValue;
            }
            return value;
        }
    }
}

让我担心的是,传递属性的名称违反了DRY,并且很容易意外地传递错误的字符串。

如何改进此代码以删除重复?

3 个答案:

答案 0 :(得分:3)

您没有说明您使用的是哪个版本的框架,但如果它是.NET 4.5或更高版本,您可以使用CallerMemberName。将以下方法添加到MyClass

private PropertyInfo GetProperty([CallerMemberName] string name = "")
{
   var myPropertyInfo = this.GetType().GetProperty(name);
   return myPropertyInfo;
}

然后,在MyProperty更改

var myPropertyInfo = this.GetType().GetProperty("MyProperty");

var myPropertyInfo = this.GetProperty();

在运行时,系统会自动为您提供name GetProperty参数的值。

实际上,如果你这么做(并且它总是相同的属性),你可以更加简化:

private string GetDefaultValueForProperty([CallerMemberName] string name = "")
{
    string defaultValue = null;
    var myPropertyInfo = this.GetType().GetProperty(name);
    var myAttributeInfo = myPropertyInfo.GetCustomAttribute<DefaultValueAttribute>();
    if (myAttributeInfo != null)
    {
        defaultValue = (string)myAttributeInfo.Value;
    }

    return defaultValue;
}

然后,您的媒体资源中的代码如下所示:

[DefaultValue("This is my default")]
public string MyProperty
{
    get
    {
        string value = this.db.getMyProperty();
        if (value == null)
        {
            value = GetDefaultValueForProperty();
        }
        return value;
    }
}

答案 1 :(得分:2)

使用MethodBase.GetCurrentMethod()从方法或属性获取当前引用。在您的情况下,使用Name属性,该属性将返回字符串get_MyProperty,并使用get_删除substring部分,请尝试以下操作:

[DefaultValue("This is my default")]
public string MyProperty
{
    get
    {
        string value = this.db.getMyProperty();
        if (value == null)
        {
            // get property name from GetCurrentMethod.
            // use the SubString to remove the "get_" that comes from .net internals
            var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4);

            // keep your method
            var myPropertyInfo = this.GetType().GetProperty(propertyName);
            var myAttributeInfo = myPropertyInfo.GetCustomAttribute(
                typeof (DefaultValueAttribute)) as DefaultValueAttribute;
            if (myAttributeInfo != null)
                value = myAttributeInfo.defaultValue;
        }
        return value;
    }
}

答案 2 :(得分:1)

您可以使用这样的扩展方法:

public static TValue GetDefaultValue<TParent, TValue>
  (this TParent @this, Expression<Func<TParent, TValue>> e)
{
  var member = (e.Body as MemberExpression).Member;
  var attr = member.GetCustomAttribute(typeof (DefaultValueAttribute)) 
               as DefaultValueAttribute;

  return (TValue)attr.Value;
}

现在你只需要在你的财产中这样做:

return GetDefaultValue(i => i.MyProperty);

更好,并且使用编译时检查,它也适用于重构:)

扩展方法非常简单,你希望它更安全,但这个想法应该是明确的。