Stringify member name similar to #define str(s) #s

2019-09-07 19:08发布

Is there any way to stringify a member name in C# for .NET 4.0 like you would in C by using the #define str(s) #s macro?

public Double MyDouble
{
    get { return _MyDouble;}
    set 
    { 
        _MyDouble = value; 
        RaisePropertyChanged("MyDouble");
        // The below item would refactor correctly if C# had a stringify pre-processor
        // RaisePropertyChanged(str(MyDouble));
    }
}
private Double _MyDouble;

Re-factorization breaks the raise property changed event if I have Search in Strings disabled or breaks completely unrelated strings if it is enabled. Sometimes I won't notice until a UI element no longer responds to changes.

3条回答
我命由我不由天
2楼-- · 2019-09-07 19:40

No, unfortunately. Currently you would have to use something like PostSharp or NotifyPropertyWeaver to do this reliably.

Note that in C# 5 you'll be able to do this:

public void RaisePropertyChanged([CallerMemberName] string member = "")
{
}

And you would use it like so:

public Double MyDouble
{
    get { return _MyDouble;}
    set 
    { 
        _MyDouble = value; 
        RaisePropertyChanged();
    }
}

And the C# 5 compiler will automatically fill in the the optional parameter.

查看更多
甜甜的少女心
3楼-- · 2019-09-07 19:53

For your specific case of OnPropertyChanged the best you could do is the following (though not ideal obviously)...

this.OnPropertyChanged(x => x.Member);

...and...

protected void OnPropertyChanged(Expression<Func<T, object>> property)
{
    var propertyName = GetPropertyName(property.Body);
    if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private static string GetPropertyName(Expression expression)
{
    switch (expression.NodeType)
    {
        case ExpressionType.MemberAccess:
            var memberExpression = (MemberExpression)expression;
            var supername = GetPropertyName(memberExpression.Expression);

            if (String.IsNullOrEmpty(supername))
                return memberExpression.Member.Name;

            return String.Concat(supername, '.', memberExpression.Member.Name);

        case ExpressionType.Call:
            var callExpression = (MethodCallExpression)expression;
            return callExpression.Method.Name;

        case ExpressionType.Convert:
            var unaryExpression = (UnaryExpression)expression;
            return GetPropertyName(unaryExpression.Operand);

        case ExpressionType.Parameter:
            return String.Empty;

        default:
            throw new ArgumentException();
    }
}

...along these lines....

查看更多
甜甜的少女心
4楼-- · 2019-09-07 19:53

I'm not familiar with the C construct, but it sounds awfully like the nameof keyword introduced in C# 6 which is

used to obtain the simple (unqualified) string name of a variable, type, or member.

If we wire it in:

public Double MyDouble
{
    get { return _MyDouble; }
    set
    {
        _MyDouble = value;

        RaisePropertyChanged(nameof(MyDouble));
    }
}

...and set a property value, RaisePropertyChanged receives a string argument of "MyDouble".

查看更多
登录 后发表回答