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



我有一个类,它有一个属性,并且该属性有一个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,并且很容易意外地传递错误的字符串。

如何改进这段代码以消除重复?

你没有说你使用的是什么版本的框架,但如果是。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();

运行时自动提供GetPropertyname参数值。

实际上,如果你经常这样做(并且总是相同的属性),你可以进一步简化:

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

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

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

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

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);

更好,有编译时检查,它也可以用于重构:)

扩展方法实际上是最基本的,您希望它更安全,但是思想应该是明确的。

相关内容

  • 没有找到相关文章

最新更新