Firing an event / function on a property? (C#)

2019-03-19 05:11发布

I am using a class that I cannot edit, it has a property (a boolean) of which it would be nice to be informed when it changes, I can't edit the properties get or set as I am importing the class from a .dll (which I don't have the code for).

How do I create an event/function that is fired when the property is changed?

Additional
It is only changed within its own class, directly to the underlying private variable.

E.g.

private bool m_MyValue = false;

public bool MyValue
  {
  get { return m_MyValue; }
  }

private void SomeFunction()
  {
  m_MyValue = true;
  }

8条回答
一纸荒年 Trace。
2楼-- · 2019-03-19 05:24

You cant do this directly [as Jon Skeet said], unless it's virtual, you're in a position to intercept all instance creations of the class and there are no changes to a backing field that influences the real 'value' of the propget.

The only way to brute force this is to use Mono.Cecil or MS CCI to instrument the prop setter a la this DimeCast on Cecil. (Or PostSharp)

However this wouldn't trap internal changes to the backing field (if there even is one). (Which is why wrapping probably wont work).

UPDATE: Given your update that you're definitely trying to trap the underlying field change, the only way to do that is to use PS / CCI / Cecil and analyse the flow to intercept all field updates. In short, not very feasible.

查看更多
手持菜刀,她持情操
3楼-- · 2019-03-19 05:30

As previously mentioned, the most direct method (and that which requires the least change to code) is to use an AOP library such as PostSharp.

However, a solution can be achieved using traditional C#/.NET by using the dependency property pattern, used throughtout WPF to great effect. I suggest to read up on this, and consider implementing such a system (or at least a simplified version of it) for your project, if appropiate.

查看更多
看我几分像从前
4楼-- · 2019-03-19 05:31

Could you inherit from the class and hide the property? Something like this...

class MyClass : BaseClass
{
    // hide base property.
    public new bool MyProperty
    {
        get
        {
            return base.MyProperty;
        }

        set
        {
            base.MyProperty = value;
            RaiseMyPropertyChangedEvent();
        }
    }
}
查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-03-19 05:37

You can try to inherit it and use it's child instead of it. Override the "set" of the property so it raises the event.

EDIT: ... only if property is virtual in the parent class ...

查看更多
兄弟一词,经得起流年.
6楼-- · 2019-03-19 05:39

You will need to create a class that wraps the class in the dll, within the setter property just raise an event there using the normal methods.

查看更多
仙女界的扛把子
7楼-- · 2019-03-19 05:42

I think Alex' idea of a wrapper is good, however, given that the most important thing to you is that you know that the value is changed before use, you could simply move the notification to the getter, circumventing the worries of internal value change. That way you get something similar to polling, yet reliable:

class MyClass : BaseClass
{
    //local value
    private bool local;

    //first access yet?
    private bool accessed = false;

    // Override base property.
    public new bool MyProperty
    {
        get
        {
            if(!accessed)
            {
                // modify first-get case according to your taste, e.g.
                local = base.MyProperty;
                accessed = true;
                RaiseMyPropertyChangedBeforeUseEvent();
            }
            else
            {
                if(local != base.MyProperty)
                {
                    local = base.MyProperty;
                    RaiseMyPropertyChangedBeforeUseEvent();
                }
            }

            return local;
        }

        set
        {
            base.MyProperty = value;
        }
    }
}
查看更多
登录 后发表回答