我有一个类,它有一个属性,并且该属性有一个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();
运行时自动提供GetProperty
的name
参数值。
实际上,如果你经常这样做(并且总是相同的属性),你可以进一步简化:
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);
更好,有编译时检查,它也可以用于重构:)
扩展方法实际上是最基本的,您希望它更安全,但是思想应该是明确的。