【问题标题】:C# How to get the name of the property being setC#如何获取正在设置的属性的名称
【发布时间】:2013-12-28 18:01:33
【问题描述】:

我有一个执行大量繁重工作的数据库对象类。然后我扩展该对象并构建代表实际对象和正在修改的字段的类。基本上是这样的:

public class MyObject : DatabaseObject
{
    public string FieldX
    {
        get { return GetValue<string>("FieldX"); }
        set { SetValue<string>("FieldX", value); }
    }

    public int FieldY
    {
        get { return GetValue<int>("FieldY"); }
        set { SetValue<int>("FieldY", value); }
    }
}

public class DatabaseObject
{
    public T GetValue<T>(string FieldName)
    {
         // Code that actually gets the right value
    }

    public void SetValue<T>(string FieldName, T value)
    {
         // Code that actually sets the value in the right place
    }
}

这样,我稍后可以实例化 MyObject 并开始通过代码设置属性。我们的想法是生成更简单、更易于维护的代码。

在实践中效果很好。但是,我注意到 MyObject 的代码非常重复。例如,对于 FieldX,我最终在 get/set 中指定“字符串”类型,并且还必须在 get/set 中指定属性名称“FieldX”。

我想知道是否有办法进一步简化代码以减少重复。

我知道我可以使用反射:

MethodBase.GetCurrentMethod().Name.Substring(4)

...在 get/set 调用中获取属性名称,我可以在设置时使用 GetType() 来获取值的类型,但理想情况下我想从内部获取原始属性名称基本的 GetValue/SetValue 方法(最好不解析堆栈跟踪)。

理想情况下,我正在寻找这样的东西:

    public string FieldX
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }

    public int FieldY
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }

有什么想法吗?

【问题讨论】:

    标签: c# reflection types properties


    【解决方案1】:

    C# 5.0 通过在默认参数上使用[CallerMemberName] 属性来支持这一点。像这样的:

    public static object GetValue([CallerMemberName] string caller = "")
    {
        Trace.WriteLine("Called by: " + caller);
        return null;
    }
    

    并且会像这样使用:

    public string FieldX
    {
        get { return (string)GetValue(); }
    }
    

    编译器会根据调用者的名字自动提供GetValue的参数。

    您可以通过in MSDN了解更多关于此功能的信息。

    您可以将GetValue 设为通用,以便在您的属性中像GetValue&lt;string&gt;() 一样使用它。

    【讨论】:

    • 我想我不能将两个答案都标记为正确。我认为上面的 C# 5.0 答案可能是正确的长期方法,但不幸的是,项目要求限制了我今天使用它,所以我不得不退回到下面的答案。
    【解决方案2】:

    这比您寻找的要长一点,但也可以使用(使用 强类型 lambda 表达式)。

    public class MyObject : DatabaseObject
    {
        public string FieldX
        {
            get { return GetValue(() => FieldX); }
            set { SetValue(() => FieldX, value); }
        }
    
        public int FieldY
        {
            get { return GetValue(() => FieldY); }
            set { SetValue(() => FieldY, value); }
        }
    }
    
    public class DatabaseObject
    {
        public T GetValue<T>(Expression<Func<T>> field)
        {
             string fieldName = GetFieldName(field);
             // Code that actually gets the right value
        }
    
        public void SetValue<T>(Expression<Func<T>> field, T value)
        {
             string fieldName = GetFieldName(field);
             // Code that actually sets the value in the right place
        }
    
        private static string GetFieldName<T>(Expression<Func<T>> field)
        {
            return ((MemberExpression)field.Body).Member.Name;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-28
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 2017-05-04
      • 2015-09-20
      • 1970-01-01
      相关资源
      最近更新 更多