How slowly is this happening? INotifyPropertyChanged using StackTrace

Today I came across an interesting method for implementing the INotifyPropertyChanged interface. Instead of passing the string name of the changed property or lambda expression, we can simply call RaisePropertyChanged (); from the setter, note that the call is without parameters. This is the code for the RaisePropertyChanged () method:

public virtual void RaisePropertyChanged()
{
    var frames = new System.Diagnostics.StackTrace();
    for (var i = 0; i < frames.FrameCount; i++)
    {
        var frame = frames.GetFrame(i).GetMethod() as MethodInfo;
        if (frame != null)
            if (frame.IsSpecialName && frame.Name.StartsWith("set_"))
            {
                RaisePropertyChanged(frame.Name.Substring(4));
                return;
            }
    }
    throw new InvalidOperationException("NotifyPropertyChanged() can only by invoked within a property setter.");
}

And this is a property that will notify its dependents of a change:

public string MyProperty
{
    get { return _myField; }
    set
    {
        _myField= value;
        RaisePropertyChanged();
    }
}

Although I find this approach interesting, I think that a performance penalty can be severe if the property has changed frequently ... or if each property in our application has used this approach to notify of its change.

I would like to hear your opinion. (the community-wiki flag is no longer selected) Will this approach be very inefficient?

: ,

+5
5

, . ( , , MethodImpl. , .)

:

Raised event using reflection 1000 times in 25.5334 ms.
Raised event WITHOUT reflection 1000 times in 0.01 ms.

, , , , 2,5 "" .

, . ( ) , ; , , .


. - , , , .

( , ), , , , , , , RaisePropertyChanged MethodImpl, MethodImplOptions.NoInlining... , , , .

, ( MethodImpl), . , .

+8

Yeesh, , , inlined.

, [MethodImplAttribute], .

, DynamicProxy, , , - . , , NotifyPropertyChanged.

    private static void SetterInterceptor<T, TProperty>(ProxiedProperty<T, TProperty> property, T target, TProperty value) where T:class,IAutoNotifyPropertyChanged
    {
        TProperty oldValue;
        if (!EqualityComparer<TProperty>.Default.Equals(oldValue = property.GetMethod.CallBaseDelegate(target), value))
        {
            property.SetMethod.CallBaseDelegate(target, value);
            target.OnPropertyChanged(new PropertyChangedEventArgs(property.Property.Name));
        }
    }

foreach , , Delegate.CreateDelegate .

+2

, , , .

0

, , :

-, , . , JITTER , .

0

, , :

, -, getter.

PropertyChanged

0

All Articles