C# 我可以在不使用属性名称的情况下获取属性信息吗?

C# 我可以在不使用属性名称的情况下获取属性信息吗?,c#,reflection,C#,Reflection,我有一个类有一个属性,该属性有一个属性,在该属性的get{}或set{}中,我想访问该属性 是否有任何方法可以在不必将属性名称作为字符串引用的情况下执行此操作?这行吗 class MyClass { [DefaultValue("This is my default")] public string MyProperty { get { string value = this.db.getMyProperty();

我有一个类有一个属性,该属性有一个
属性
,在该属性的
get{}
set{}
中,我想访问该属性

是否有任何方法可以在不必将属性名称作为
字符串引用的情况下执行此操作?这行吗

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,并且很容易意外地传递错误的字符串


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

使用
MethodBase.GetCurrentMethod()
从方法或属性获取当前引用。在您的情况下,请使用
Name
属性,该属性将返回一个字符串
get_MyProperty
,并删除带有
子字符串的
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;
    }
}

使用
MethodBase.GetCurrentMethod()
从方法或属性获取当前引用。在您的情况下,请使用
Name
属性,该属性将返回一个字符串
get_MyProperty
,并删除带有
子字符串的
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;
    }
}

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

private PropertyInfo GetProperty([CallerMemberName] string name = "")
{
   var myPropertyInfo = this.GetType().GetProperty(name);
   return myPropertyInfo;
}
然后,在
MyProperty
change中

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

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

private PropertyInfo GetProperty([CallerMemberName] string name = "")
{
   var myPropertyInfo = this.GetType().GetProperty(name);
   return myPropertyInfo;
}
然后,在
MyProperty
change中

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;
    }
}
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;
}
更好,编译时检查和重构也可以使用:)


扩展方法实际上是赤裸裸的,您希望它更安全,但想法应该清楚。

您可以使用如下扩展方法:

[DefaultValue("This is my default")]
public string MyProperty
{
    get
    {
        string value = this.db.getMyProperty();
        if (value == null)
        {
            value = GetDefaultValueForProperty();
        }
        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;
}
更好,编译时检查和重构也可以使用:)


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

这似乎比只在备份字段中设置一个默认参数,并且没有任何属性或反射更有效。我简化了问题。我们从中填充的viewmodel需要显示当前值,以及用户选择还原为默认值时将使用的值。这似乎比只在备份字段中设置默认参数而没有任何属性或反射要复杂得多。我简化了问题。我们从中填充的viewmodel需要显示当前值,以及如果用户选择还原为默认值时将使用的值。MethodBase.GetCurrentMethod()。名称为“get_MyProperty”,而不是“MyProperty”,但如果模式与它显示的一致,我可以去掉“get_MyProperty”@JeffDege:我认为模式应该是一致的。如果需要另一种方法,可以迭代所有属性以找到引用“Get”方法的属性:
var getMethod=MethodBase.GetCurrentMethod();var myPropertyInfo=this.GetType().GetProperties().Where(pinfo=>pinfo.GetGetMethod()==getMethod).First()我不会骗你,它肯定没有那么有效。但是,您正在生成一个常量值,因此您可能/应该引入缓存机制。请尝试在属性名称上应用
.Substring(4)
,以删除字符串的这一部分。它来自.Net的内部结构,我们无法更改。使用
MethodBase.GetCurrentMethod()
的问题是它将爬网堆栈帧以找到当前方法,JIT无法内联潜在优化的方法。MethodBase.GetCurrentMethod()。名称为“get\u MyProperty”,而不是“MyProperty”,但是,如果模式像它看起来那样一致,我可以去掉“get_u2;”这个词。@JeffDege:我相信模式应该是一致的。如果需要另一种方法,可以迭代所有属性以找到引用“Get”方法的属性:
var getMethod=MethodBase.GetCurrentMethod();var myPropertyInfo=this.GetType().GetProperties().Where(pinfo=>pinfo.GetGetMethod()==getMethod).First()我不会骗你,它肯定没有那么有效。但是,您正在生成一个常量值,因此您可能/应该引入缓存机制。请尝试在属性名称上应用
.Substring(4)
,以删除字符串的这一部分。它来自.Net的内部,我们无法更改
是它将爬网堆栈帧以查找当前方法,而JIT无法内联该方法以进行潜在优化。这应该有进一步的解释,说明它的作用以及它为什么以您编写的方式这样做。这应该有进一步的解释,说明它的作用以及为什么以这种方式这样做你已经写信了。