使用lambda标识属性名称

时间:2014-09-12 07:17:54

标签: c# properties lambda

我对以下代码有疑问:

public class MyClass : INotifyPropertyChanged
{
    private bool _myProp;
    public bool MyProp
    {
        get { return _myProp; }
        set
        {
            _myProp = value;                
            RaisePropertyChanged(() => MyProp);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

这可能不是识别属性名称的最佳方法,但我之前使用过它,即使在同一个项目中也是如此;但是,上面的代码将无法编译。这有几种解决方法;其中一些可能是更好的解决方案,但是,我仍然想知道为什么这不起作用。

我得到的具体编译错误是:

error CS1660: Cannot convert lambda expression to type 'string' because it is not a delegate type

3 个答案:

答案 0 :(得分:2)

签出新的CallerMemberName属性。我只通过mvvm灯发现了它,但永远不会再通过旧的方式改变旧的方式。

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

答案 1 :(得分:0)

您需要一个接受Expression<Func<T>>的方法,将属性名称提取为字符串,然后使用它引发PropertyChanged事件。它不会自动完成。我通常把它作为一个扩展方法,一遍又一遍地保存相同的代码或者在基类中保存它:

public static class RaisePropertyChangedExtensions
{
    public static void RaisePropertyChanged<T>(
        this IRaisePropertyChanged raisePropertyChangedImpl,
        Expression<Func<T>> expr)
    {
        var memberExprBody = expr.Body as MemberExpression;
        string property = memberExprBody.Member.Name;
        raisePropertyChangedImpl.RaisePropertyChanged(property);
    }
}

您的视图模型只需要实现IRaisePropertyChanged接口:

public interface IRaisePropertyChanged : INotifyPropertyChanged
{
    void RaisePropertyChanged(string property);
}

..用法与您的问题完全相同:

this.RaisePropertyChanged(() => MyProp);

当然,您总是可以在视图模型上创建一个方法 - 只需删除泛型参数并将视图模型类型传递给函数。

答案 2 :(得分:0)

您需要使用表达式:

public static string GetPropertyName<T, TPropValue>(this Expression<Func<T, TPropValue>> propertySelector) where T : class
{
    Condition.Requires(propertySelector, "propertySelector").IsNotNull();

    var memberExpr = propertySelector.Body as MemberExpression;
    if (memberExpr == null)
         throw new ArgumentException("Provider selector is not property selector.");

    var propInfo = memberExpr.Member as PropertyInfo;       
    if (propInfo == null)
         throw new NotSupportedException("You can properties only.");

    return propInfo.Name;
}

protected void RaisePropertyChanged(Expression<Func<MyClass, string>> propSelector) 
{  
   if (PropertyChanged != null)
   {
       var propertyName = propertySelecotr.GetPropertyName();
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
}

用法:

RaisePropertyChanged(myClass => myClass.MyProp);