(见下面我用我接受的答案创建的解决方案)

我试图提高一些涉及反射的代码的可维护性。该应用程序有一个。net Remoting接口,其中包括一个名为Execute的方法,用于访问应用程序中未包含在其发布的远程接口中的部分。

下面是应用程序如何指定属性(本例中的静态属性),这意味着可以通过Execute访问:

RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");

因此远程用户可以调用:

string response = remoteObject.Execute("SomeSecret");

应用程序将使用反射来查找SomeClass。SomeProperty并以字符串形式返回它的值。

不幸的是,如果有人重命名SomeProperty并且忘记更改ExposeProperty()的第3个参数,就会破坏这个机制。

我需要的是:

SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()

作为ExposeProperty中的第三个parm,这样重构工具就会照顾到重命名。

有办法做到这一点吗?

好吧,这是我最终创建的(基于我选择的答案和他引用的问题):

// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
    var me = propertyLambda.Body as MemberExpression;

    if (me == null)
    {
        throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
    }

    return me.Member.Name;
 }

用法:

// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);

// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);

现在有了这个很酷的功能,是时候简化ExposeProperty方法了。擦门把手是危险的工作。


当前回答

我一直在使用这个答案,效果很好:从表达式<Func<TModel,TProperty>>中获取属性,作为字符串

我意识到我之前已经回答过这个问题。我的其他答案的唯一优点是它适用于静态属性。我发现这个答案中的语法更有用,因为您不必创建想要反映的类型的变量。

其他回答

有一个著名的黑客从lambda表达式中提取它(这是来自PropertyObserver类,由Josh Smith在他的MVVM基金会):

    private static string GetPropertyName<TPropertySource>
        (Expression<Func<TPropertySource, object>> expression)
    {
        var lambda = expression as LambdaExpression;
        MemberExpression memberExpression;
        if (lambda.Body is UnaryExpression)
        {
            var unaryExpression = lambda.Body as UnaryExpression;
            memberExpression = unaryExpression.Operand as MemberExpression;
        }
        else
        {
            memberExpression = lambda.Body as MemberExpression;
        }

        Debug.Assert(memberExpression != null, 
           "Please provide a lambda expression like 'n => n.PropertyName'");

        if (memberExpression != null)
        {
            var propertyInfo = memberExpression.Member as PropertyInfo;

            return propertyInfo.Name;
        }

        return null;
    }

抱歉,这里缺少一些上下文。这是一个更大的类的一部分,其中TPropertySource是包含属性的类。您可以将TPropertySource中的函数设为泛型,以便从类中提取它。我建议查看来自MVVM基金会的完整代码。

好吧,这是我最终创建的(基于我选择的答案和他引用的问题):

// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>

public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
    var me = propertyLambda.Body as MemberExpression;

    if (me == null)
    {
        throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
    }

    return me.Member.Name;
 }

用法:

// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);

// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);

您可以使用StackTrace类来获取当前函数的名称(或者如果您将代码放在函数中,则降低一级并获取调用函数)。

见http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace (VS.71) . aspx

如果我理解正确的话,PropertyInfo类应该帮助您实现这一点。

Type.GetProperties()方法 PropertyInfo[] propInfos = typeof(ReflectedType).GetProperties(); propInfos.ToList()。ForEach (p = > Console.WriteLine(字符串。格式("属性名:{0}",p.Name));

这是你需要的吗?

我修改了您的解决方案,以链接多个属性:

public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
    MemberExpression me = propertyLambda.Body as MemberExpression;
    if (me == null)
    {
        throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
    }

    string result = string.Empty;
    do
    {
        result = me.Member.Name + "." + result;
        me = me.Expression as MemberExpression;
    } while (me != null);

    result = result.Remove(result.Length - 1); // remove the trailing "."
    return result;
}

用法:

string name = GetPropertyName(() => someObject.SomeProperty.SomeOtherProperty);
// returns "SomeProperty.SomeOtherProperty"