如何在不知道数据类型的情况下使用属性更改事件传递数据?

时间:2016-03-06 18:11:57

标签: c# events generics

是否有一种优雅的方式来设置属性更改事件,其中包括当您不知道派生类中可包含哪些类型的数据时更改的数据?

例如:

// I know I'm abusing the generics notation and this will not compile,
// but hopefully it will get my point across about what I'm trying to do.

class PropertyChangedEventArgs<T> : EventArgs
{
    public string PropertyName { get; private set; }
    public T Data { get; private set; }

    public PropertyChangedEventArgs(string name, T data)
    {
        PropertyName = name;
        Data = data;
    }
}

public class Person
{
    public event EventHandler<PropertyChangedEventArgs<T>> PropertyChanged = delegate { };

    public int Age {
        get;
        protected set {
            if (_age != value) {
                _age = value;
                OnPropertyChanged(new PropertyChangedEventArgs<int>("Age", _age));
            }
        }
    } private int _age;

    // More properties...

    protected void OnPropertyChanged(PropertyChangedEventArgs<T> eventArgs)
    {
        EventHandler<PropertyChangedEventArgs<T>> handler = PropertyChanged;
        if (handler != null) {
            handler (this, PropertyChangedEventArgs<T>);
        }
    }
}

// Later we might want something like this, but we want to use the same event handler

public class Athlete : Person
{   
    public CholesterolNumbers Cholesterol {
        get { return _cholesterol; }
        protected set {
            if (!_cholesterol.Equals(value)) {
                _cholesterol = value;

                // Same event, different data type:
                OnPropertyChanged(new PropertyChangedEventArgs<CholesterolNumbers>("Cholesterol", _cholesterol));
            }
        }
    } private CholesterolNumbers _cholesterol;

    public struct CholesterolNumbers {
        public int LDL;
        public int HDL;
        public int Trig;

        public CholesterolNumbers(int ldl, int hdl, int trig)
        {
            LDL = ldl;
            HDL = hdl;
            Trig = trig;
        }
    }
}

是否有一种巧妙的方法,这样任何派生类都可以使用相同的EventHandler,我们不必为我们稍后添加的每种类型编写一个全新的EventArgs类?我看到了this solution一个非常相似的问题,但他们的方法仍然为每个单独命名的类型都有事件。我试图避免这种情况。

可以这样做吗?或者我应该重新考虑我的方法?

1 个答案:

答案 0 :(得分:1)

由于为公共属性引发了PropertyChanged,您可以直接在目标对象中查询属性的值,而不是在事件中传递它。例如,Windows窗体中的Resize事件(以及ClickDoubleClick等)不会带有宽度和高度信息。相反,您可以直接致电Form.WidthForm.Height来获取这些值。

这种情况不起作用的一种情况是,您希望同时获取属性的旧值和新值,因为在客户端收到有关更改的通知时,旧值已被覆盖。 PropertyChanging模式提供了这个问题的优雅解决方案。在更改属性之前,类会立即引发此事件,从而允许客户端在其中一个值丢失之前读取旧值和新值。