Повышение события из базового класса - PullRequest
4 голосов
/ 25 января 2009

Я понимаю, что можно вызвать событие в классе, в котором происходит объявление реализации, но я хочу вызвать событие на уровне базового класса и вызвать событие производного класса:

public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs  e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    public virtual event EventHandler<FooEventArgs> FooValueChanged;

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        FooValueChanged(sender, e);
    }
}

У меня не может быть абстрактного события FooValueChanged, потому что тогда базовый класс не может вызвать событие. Текущий код выполняется, но вызов FooValueChanged (sender, e) генерирует исключение NullReferenceException, поскольку он не вызывает событие производного класса, а только событие базового класса.

Куда я иду не так?

Я могу иметь абстрактное событие и сборщик, но тогда мне нужно помнить, чтобы вызывать FooValueChanged (sender, e) в каждом производном классе. Я пытаюсь избежать этого, когда могу использовать конструктор Visual Studio для производных элементов управления.

Ответы [ 3 ]

10 голосов
/ 25 января 2009

Обратите внимание, что объявление события, которое вы используете, является сокращенной записью в C #:

public event EventHandler Event;
public void RaiseEvent() {
    this.Event(this, new EventArgs());
}

Эквивалентно:

private EventHandler backEndStorage;
public event EventHandler Event {
    add { this.backEndStorage += value; }
    remove { this.backEndStorage -= value; }
}
public void RaiseEvent() {
    this.backEndStorage(this, new EventArgs());
}

Где backEndStorage - многоадресный делегат.


Теперь вы можете переписать свой код:

public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs  e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    protected event EventHandler<FooEventArgs> backEndStorage;
    public event EventHandler<FooEventArgs> FooValueChanged {
        add { this.backEndStorage += value; }
        remove { this.backEndStorage -= value; }
    }

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        this.backEndStorage(sender, e);
    }
}

public class FooDerived : FooBase {
    public event EventHandler<FooEventArgs> AnotherFooValueChanged {
        add { this.backEndStorage += value; }
        remove { this.backEndStorage -= value; }
    }
}

Так что теперь, когда события добавляются в производный класс, они фактически добавляются в backEndStorage базового класса, что позволяет базовому классу вызывать делегаты, зарегистрированные в производном классе.

2 голосов
/ 25 января 2009

Окончательный результат:

public interface IFoo
{
    event EventHandler<FooEventArgs> FooValueChanged;
    void RaiseFooValueChanged(IFooView sender, FooEventArgs e);
}

[TypeDescriptionProvider(typeof(FooBaseImplementor))]
public abstract class FooBase : Control, IFoo
{
    protected event EventHandler<FooEventArgs> backEndStorage;
    public abstract event EventHandler<FooEventArgs> FooValueChanged;

    public void RaiseFooValueChanged(IFooView sender, FooEventArgs e)
    {
        if (backEndStorage != null)
            backEndStorage(sender, e);
    }
}

public class FooDerived : FooBase {
    public override event EventHandler<FooEventArgs> FooValueChanged {
        add { backEndStorage += value; }
        remove { backEndStorage -= value; }
    }
}
1 голос
/ 25 января 2009

Зачем вам нужно использовать событие? Разве вы не можете просто использовать переопределенный метод. База вызывает переопределяемый метод, который «перехватывается» производным классом, который затем может вызвать событие?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...