Как Virtual event, который override в наследниках может вызвать все обработчики в любом их наследников
Вопрос в том как мне набрать обработчиков событий в базовый класс из нескольких наследников таким образом чтобы была возможность вызывать ВСЕ событие из базового класса, любого из его наследников и из вне
Небольшой пример для конкретизации. Самое главное что бы в SomeMethod класса А вызывались все набранные обработчики, но при их добавлении через += они идут не в бейс.
public abstract class A
{
public delegate void D1(bool IsConnected);
public virtual event D1 EV1;
public void SomeMethod()
{
//TODO
EV1?.Invoke(true); //Тут нужно что бы вызывались все обработчики добавленные в любом из наследников
//TODO
}
public void InitEvent(D1 d1)
{
EV1 = d1;//тут ивент был null
}
}
public class B : A
{
public void SomeMethod_B()
{
//TODO
InitEvent(new D1(B_handler));//Добавляю обработчик из класса Б
//TODO
}
public void B_handler(bool IsConnected)
{
//TODO
}
}
public class C : B
{
public override event D1 EV1; // Ставлю оверрайд так как без него нельзя инвокать
public void SomeMethod_C()
{
//TODO
EV1 += new D1(C_handler); //Добавляю обработчик из класса C, но он идет не в бейс а в этом скоупе
EV1?.Invoke(true);
//TODO
}
public void SomeMethod_C2()
{
//TODO
EV1?.Invoke(true);
//TODO
}
public void C_handler(bool IsConnected)
{
//TODO
}
}
public class D
{
public D()
{
var test = new C();
test.EV1 += Test_EV1;// Добавляю обработчик
test.SomeMethod_B(); //Добавляю обработчик из класса Б в base abstract
test.SomeMethod_C(); //Добавляю обработчик
test.SomeMethod_C2(); //Нужно что бы он вызвал сразу все 2 добавленых хендлера и это Работает
test.SomeMethod(); //Нужно что бы он вызвал сразу все 3 добавленых хендлера но вызывается только B_handler
}
private void Test_EV1(bool IsConnected)
{
//TODO
}
}
Или может быть есть иной подход, о котором я не в теме так что бы несколько обработчиков набранных в разных местах и в разное время могли вызыватся из нескольких мест
Ответы (1 шт):
По сути ваш вопрос можно свести к ошибке CS0070 The event '...' can only appear on the left hand side of += or -=.
Если упростить пример, то он выглядел бы вот так
public abstract class BaseClass
{
public event Action SomethingChanged;
public BaseClass()
{
SomethingChanged += BaseHandler;
}
private void BaseHandler()
{
Console.WriteLine("BaseHandler");
}
}
public class MyClass : BaseClass
{
public MyClass()
{
SomethingChanged += MyHandler;
}
public void Execute()
{
SomethingChanged?.Invoke(); // Error CS0070 The event 'BaseClass.SomethingChanged' can only appear on the left hand side of += or -= (except when used from within the type 'BaseClass')
}
private void MyHandler()
{
Console.WriteLine("MyHandler");
}
}
Чтобы этого избежать, нужно инвокающий метод поместить в базовый класс, а в наследнике его просто вызвать.
public abstract class BaseClass
{
public event Action SomethingChanged;
public BaseClass()
{
SomethingChanged += BaseHandler;
}
protected void OnSomethingChanged()
{
SomethingChanged?.Invoke();
}
private void BaseHandler()
{
Console.WriteLine("BaseHandler");
}
}
public class MyClass : BaseClass
{
public MyClass()
{
SomethingChanged += MyHandler;
}
public void Execute()
{
OnSomethingChanged();
}
private void MyHandler()
{
Console.WriteLine("MyHandler");
}
}
Ошибка пропала, проверяем.
static void Main(string[] args)
{
var item = new MyClass();
item.Execute();
Console.ReadKey();
}
Вывод в консоль
BaseHandler
MyHandler