How to force an event to occur from an extension method?

Asked

Viewed 62 times

1

I am creating a C# application and I am using the interface INotifyPropertyChanged thus:

public class Test: INotifyPropertyChanged
{
    private int foo;
    public int Foo { get => foo; set => Set(ref foo, value); }

    public void Set<T>(ref T property, T value, [CallerMemberName]string p = "")
    {
        property = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
    }

}

My problem is that whenever I want to implement this way of working (with the method Set(ref property, value) i am obliged to come here and copy the code and reimplementit. From this problem, I thought of an extension method like this:

using System.Runtime.CompilerServices;

public static class Extensions 
{
    public static void Set<T>(
        this INotifyPropertyChanged source, ref T property, T value,
        [CallerMemberName]string propertyName = "")
    {
        property = value;
        source.PropertyChanged?
            .Invoke(source, new PropertyChangedEventArgs(propertyName));
    }
}

My problem is that if I try to do this implementation, I get this message:

The Event INotifyPropertyChanged.PropertyChanged can only appear on the left hand side of += or -=

What I need to do to get me to force the call from that event through an extension property?

  • Tried to call as this.? Or without the extension syntax and call the static method normally, until passing the this?

  • Hmm I haven’t tried... I’ll do it here, 1 me...

  • It really doesn’t work... if I play a this there he understands that I am trying to reference the static class Extensions. I would have to call the event within source

  • Why don’t you make a base class, say, MyPropertyChanged, implements the function Set in it and when you need it, rather than implementing INotifyPropertyChanged you inherit from MyPropertyChanged where the function already exists Set defined. So it is usually done in the MVVM templates where you have a BaseViewModel where you implement only once the INotifyPropertyChanged

1 answer

1


I don’t have the slightest idea of what you want to do, because it doesn’t have the full implementation, it seems something very wrong, but to strictly solve your problem you have to pass the event handler as parameter to the desired method and call explicitly. I actually saw no advantage in having it as an extension method.

I had to put some other things to satisfy the interface:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Program {
    public static void Main() {
        var x = new Test();
        x.Foo = 10;
    }
}
public class Test: INotifyPropertyChanged {
    private int foo;
    public int Foo { get => foo; set => this.Set(ref foo, value, PropertyChanged); }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(name));
    }
}

public static class Extensions {
    public static void Set<T>(
        this INotifyPropertyChanged source, ref T property, T value, PropertyChangedEventHandler handler, [CallerMemberName]string propertyName = "") {
        property = value;
        handler?.Invoke(source, new PropertyChangedEventArgs(propertyName));
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

  • the idea was to try to create globally a way to generate observable structures without me having to rewrite code many times...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.