1

I want to observe a property of a class that did not implement INotifyPropertyChanged.

Is there any way to achieve that? It would be great if I could create some generic class or base class to inherit from it and to work with.

Sinatr
  • 20,892
  • 15
  • 90
  • 319
sj13
  • 13
  • 5
  • 2
    Why can't you just implement `INotifyPropertyChanged`? Are you simply looking for a [better way](https://stackoverflow.com/q/1315621/1997232) to implement it? – Sinatr Apr 09 '21 at 07:09
  • You can try to use [same approach](https://stackoverflow.com/q/40972605/1997232) as bindings in wpf do, when data context doesn't implement `INotifyPropertyChanged`. You still need to rise notification somewhere though. – Sinatr Apr 09 '21 at 07:11
  • @Sinatr The fact is I did not create these classes something like built-in Classes and I don't want just WPF I want it in console or DLL. – sj13 Apr 09 '21 at 07:25
  • Can you be more specific? It looks like [XY problem](https://meta.stackexchange.com/q/66377/299295). – Sinatr Apr 09 '21 at 07:26
  • @Sinatr ok I have a Process object in this case it is the brave browser I want to know about its threads and perform a task every time that changes. – sj13 Apr 09 '21 at 07:38
  • "brave browser"? What task you want to perform? What means if thread changes? Single process can spawn many threads, what you want to know? Just the number of threads? Do you want to debug or something else? – Sinatr Apr 09 '21 at 07:41
  • Ask yourself [5 whys](https://en.wikipedia.org/wiki/Five_whys) and write the root cause please. – Sinatr Apr 09 '21 at 07:42
  • @Sinatr I'm trying to create a custom task manager and want to log some detailed information of processes the thing is its changing in time, in the thread part I want to know how many thread is running and current priority and uptime of them – sj13 Apr 09 '21 at 08:18
  • 1
    I believe for such tasks you just need to poll values and that's how windows task manager works. – Sinatr Apr 09 '21 at 08:26

1 Answers1

0

If you can't change your class where you need the event, you can use this wrapper:

public class NotifyPropertyChangedWrapper<T> : INotifyPropertyChanged
{
    private readonly T item;
    public event PropertyChangedEventHandler PropertyChanged;

    public NotifyPropertyChangedWrapper(T item)
    {
        this.item = item;
    }

    public TProp Get<TProp>(Expression<Func<T, TProp>> exp)
    {
        MemberExpression memExp = exp.Body as MemberExpression;
        var property = memExp.Member as PropertyInfo;
        return (TProp)property.GetValue(item);
    }

    public void Set<TProp>(Expression<Func<T, TProp>> exp, TProp newValue)
    {
        MemberExpression memExp = exp.Body as MemberExpression;
        var property = memExp.Member as PropertyInfo;
        property.SetValue(item, newValue);
        PropertyChanged?.Invoke(item, new PropertyChangedEventArgs(property.Name));
    }
}

If you use it, you only set and get the properties via the wrapper's set and get methods. If you do so, the NotifyPropertyChanged event will be invoked. Here is an example usage

class Test
{
    public int SomeProperty { get; set; }
}

var notify = new NotifyPropertyChangedWrapper<Test>(new Test());
notify.PropertyChanged += (s, e) => Console.WriteLine(e.PropertyName);
notify.Set(x => x.SomeProperty, 10);
Console.WriteLine(notify.Get(x => x.SomeProperty));

Here is an online demo: https://dotnetfiddle.net/oVE4WW

SomeBody
  • 7,515
  • 2
  • 17
  • 33
  • @sj13 Please be aware that it is more some proof of conecpt than code that should be used in acutal software. For example, if you call the Get and Set methods with an arbitrary expression, a NullReferenceException will be thrown. Also, one could consider to invoke the PropertyChanged event only if newValue is different from the property's current value and so on. – SomeBody Apr 09 '21 at 12:03