C# Class.PropertyName上的开关大小写(非值)

C# Class.PropertyName上的开关大小写(非值),c#,.net-4.5,C#,.net 4.5,我有一个类实现了INotifyPropertyChanged,如下所示: public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; string _color; public string Color { get{ return _color; } set {

我有一个类实现了
INotifyPropertyChanged
,如下所示:

public class Person : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    string _color;
    public string Color
    {
        get{ return _color; }
        set
        {
            _color = value;
            RaisePropertyChanged();
        }
    }

    ...        

    private void RaisePropertyChanged([CallerMemberName]string prop = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}
void Person_PropertyChanged(object sender, PropertyChangedEventArgs e){
    switch (e.PropertyName)
    {
        case PropertyNameOf(Person.Color);
            //some stuff
            break;
        default:
            break;
    }
}
当调用
Color
属性设置器时,它调用
RaisePropertyChanged()
,该设置会自动获取属性名称,即
“Color”
,并使用该名称填充
PropertyChangedEventArgs
。而不是手动键入属性名称

这很好,因为它可以防止代码中可能出现的错误,因为您不必手动键入属性名。在重构代码时也会有所帮助,因为您不需要硬编码任何字符串

我的问题
我有一个
PropertyChanged
的事件处理程序。如何使用switch case构造而不将属性名硬编码为字符串。比如说:

public class Person : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    string _color;
    public string Color
    {
        get{ return _color; }
        set
        {
            _color = value;
            RaisePropertyChanged();
        }
    }

    ...        

    private void RaisePropertyChanged([CallerMemberName]string prop = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}
void Person_PropertyChanged(object sender, PropertyChangedEventArgs e){
    switch (e.PropertyName)
    {
        case PropertyNameOf(Person.Color);
            //some stuff
            break;
        default:
            break;
    }
}

这可能吗?我想这样做,这样我就可以保留上面提到的好处。

您可以使用
表达式来做您想做的事情

定义此方法:

private string ToPropertyName<T>(Expression<Func<T>> @this)
{
    var @return = string.Empty;
    if (@this != null)
    {
        var memberExpression = @this.Body as MemberExpression;
        if (memberExpression != null)
        {
            @return = memberExpression.Member.Name;
        }
    }
    return @return;
}
现在您有了一些强类型的joy.:-)


要获得类似开关的功能,而不使用
开关
和凌乱的
如果
/
/
其他
,可以执行以下操作:

void Person_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var @switch = new Dictionary<string, Action>()
    {
        { ToPropertyName(() => Person.Color), () => { /* some stuff */ } },
        { ToPropertyName(() => Person.Size), () => { /* some other stuff */ } },
        { ToPropertyName(() => Person.Shape), () => { /* some more stuff */ } },
    };

    if (@switch.ContainsKey(e.PropertyName))
    {
        @switch[e.PropertyName]();
    }
    else
    {
        /* default stuff */
    }
}
void Person\u PropertyChanged(对象发送者,PropertyChangedEventArgs e)
{
var@switch=newdictionary()
{
{ToPropertyName(()=>Person.Color),()=>{/*一些东西*/},
{ToPropertyName(()=>Person.Size),()=>{/*其他一些东西*/}},
{ToPropertyName(()=>Person.Shape),()=>{/*还有一些东西*/}},
};
if(@switch.ContainsKey(e.PropertyName))
{
@开关[e.PropertyName]();
}
其他的
{
/*默认材料*/
}
}
在C#6.0中,可以使用关键字

关键字在编译时被字符串文字替换。因此,从性能角度来看,它比在代码中使用lambda表达式要好得多,因为代码在运行时会挖掘符号的名称,而且它还可以与
switch()
语句一起使用:

switch(e.PropertyName)
{
    case nameof(Foo.Bar):
        break;
}

如果在类中更改属性的名称,但忘记在switch语句中更改,也会出现编译时错误。因此,这种方法不太容易出现错误。

案例中你需要做什么?@NateBarbettini一些东西。我省略了它,因为我认为它与您正在寻找的C#6的
nameof
运算符的问题无关。@Krimson我想您可以使用反射来查找对象的可用属性并比较。。。但我并没有仔细考虑你的例子
nameof
似乎确实是您要找的。@Krimson:C#6可以编译到2.0之后的任何.Net版本。您可以使用VS2015并继续以.Net 4.5.0为目标!谢谢!一个问题。由于
Color
是一个非静态字段,您如何处理
Person.Color
呢?@Krimson-编写此代码是为了处理非静态字段/属性。@Enigmativity该函数按预期工作,但是,我认为不可能在开关情况下使用它,因为每种情况都需要一个常量值。无论哪种方式,这个问题都超出了我最初问题的范围。我将坚持使用if-else语句。谢谢:)@Krimson-很好的呼叫重新切换
。我尽量避免切换
,所以我添加了一个替代方案。