Reputation: 11700
I have a class that has a property, and that property has an attribute
, and within the get{}
or set{}
of that property, I want to access that attribute.
Is there any way of doing this without having to reference the name of the property as a string
? Does this work?
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;
}
}
}
What causes me concern about this is that passing the name of the property is a violation of DRY, and makes it too easy to accidentally pass the wrong string.
How can I improve this code to remove duplication?
Upvotes: 0
Views: 391
Reputation: 38608
Use MethodBase.GetCurrentMethod()
to get the current reference from method or a property. In your case, use the Name
property which will return a string get_MyProperty
and remove the get_
part with substring
, Try this:
[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;
}
}
Upvotes: 2
Reputation: 42516
You don't say what version of the Framework you're using, but if it's .NET 4.5 or later you can use CallerMemberName
. Add the following method to MyClass
:
private PropertyInfo GetProperty([CallerMemberName] string name = "")
{
var myPropertyInfo = this.GetType().GetProperty(name);
return myPropertyInfo;
}
Then, in MyProperty
change
var myPropertyInfo = this.GetType().GetProperty("MyProperty");
to
var myPropertyInfo = this.GetProperty();
At runtime, the value for name
parameter of GetProperty
will be provided automatically for you.
Actually, if you're doing this a lot (and it's always the same attribute) you could simplify this even more:
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;
}
Then the code in your property looks like this:
[DefaultValue("This is my default")]
public string MyProperty
{
get
{
string value = this.db.getMyProperty();
if (value == null)
{
value = GetDefaultValueForProperty();
}
return value;
}
}
Upvotes: 3
Reputation: 63732
You can use an extension method like this:
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;
}
And now you only have to do this in your property:
return GetDefaultValue(i => i.MyProperty);
Nicer and with compile-time checks and it works with refactoring too :)
The extension method is really bare-bone, you want it to be safer, but the idea should be clear.
Upvotes: 1