C#如何获取正在设置的属性的名称

时间:2013-12-10 23:41:00

标签: c# reflection types properties

我有一个数据库对象类,它做了很多繁重的工作。然后,我扩展该对象并构建表示要修改的实际对象和字段的类。它基本上是这样的:

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中指定了“string”类型,并且还必须在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); }
    }

有什么想法吗?

2 个答案:

答案 0 :(得分:7)

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<string>()

答案 1 :(得分:3)

这比您要查找的要长一些,但也可以使用(使用强类型 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;
    }
}