如何使用lambda获取作为参数发送的属性的名称

时间:2014-09-09 12:26:36

标签: c# generics reflection expression

我可以有这样的方法:

public void MyMethod<T, TResult>( string propertyName, ... ){
    var name = propertyName;
    return {property with correct name from some object that is of type TResult}
}

并称之为:

MyMethod<SomeClass>("SomePropertyName");

获取方法内的propertyname。但是,我不喜欢在将来SomeClass更改的情况下将该属性名称作为字符串发送,并且编译器无法验证propertyName是否与类型TResult的属性匹配。

我宁愿这样称呼:

MyMethod<SomeClass>(c => c.SomePropertyName);

但我不确定我的方法会是什么样子。我尝试过这个变种:

public void MyMethod<T>( Func<T,TResult> property, ... ){
    var name = {do some cleverness on property here to extract the actual name of the property inside the expression};
    return {property with correct name from some object that is of type TResult}
}

在C#中有什么好的干净方法吗?

3 个答案:

答案 0 :(得分:3)

您无法详细调查Func<>个代表。你想询问一个Expression ......这样的事情(没有经过测试......但应该接近):

public void MyMethod<T>(Expression<Func<T,TResult>> expr, ... ){
    var expression = (MemberExpression)expr.Body;
    var name = expression.Member.Name;

    // .. the rest here using "name"
}

用法是一样的:

MyMethod<User>(u => u.UserId); // name will be "UserId"

答案 1 :(得分:1)

这是我为RaisePropertyChanged方法

执行此操作的方法
internal static class PropertySupport
{
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        if (propertyExpression == null)
        {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpression.Body as MemberExpression;
        if (memberExpression == null)
        {
            throw new ArgumentException("propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null)
        {
            throw new ArgumentException("propertyExpression");
        }

        var getMethod = property.GetGetMethod(true);
        if (getMethod.IsStatic)
        {
            throw new ArgumentException("propertyExpression");
        }

        return memberExpression.Member.Name;
    }
}

和使用PropertySupport的方法:

protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
    var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
    this.RaisePropertyChanged(propertyName);
}

我可以使用

RaisePropertyChanded<String>(() => this.MyString);

如您所见,lambda非常简单。

答案 2 :(得分:0)

[callermembername]会为你工作吗?您可以像使用它一样使用它:

public void MyMethod<T>([CallerMemberName]string caller = null){
    //leave caller blank and it will put the name of the calling member in as a string
}

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx