EventHandler 冒泡
EventHandler bubbling up
我想通过 classes 发送消息。我使用了事件并这样做了:
public class TopLevel{
public event EventHandler<string> Message;
public MiddleLevel mid;
public TopLevel()
{
mid.Message += (s, e) => { Message(s, e) };
}
}
public class MiddleLevel{
public event EventHandler<string> Message;
public BottomLevel bottom;
public MiddleLevel()
{
bottom.Message += (s, e) => { Message(s, e) };
}
}
public class BootomLevel{
public event EventHandler<string> Message;
public void DoSomething()
{
Message?.Invoke(this, "I did it.");
}
}
public class Handler{
public void HandleEvent(TopLevel top)
{
top.Message += PrintMessage;
}
public void PrintMessage(object sender, string message)
{
Console.WrteLine(message);
}
}
还尝试将构造函数更改为 lambda 表达式,如下所示:
public class TopLevel{
public event EventHandler<string> Message;
public MiddleLevel mid;
public TopLevel()
{
mid.Message += (s, e) => { Message?.Invoke(s, e); };
}
}
public class MiddleLevel{
public event EventHandler<string> Message;
public BottomLevel bottom;
public MiddleLevel()
{
bottom.Message += (s, e) => { Message?.Invoke(s, e); };
}
}
public class BootomLevel{
public event EventHandler<string> Message;
public void DoSomething()
{
Message?.Invoke(this, "I did it.");
}
}
public class Handler{
public void HandleEvent(TopLevel top)
{
top.Message += PrintMessage;
}
public void PrintMessage(object sender, string message)
{
Console.WrteLine(message);
}
}
以上代码不打印任何消息。即使我在 MiddleLevel class 中处理事件,我仍然没有收到消息。我认为这是因为消息调用是在构造函数中进行的(即使 linq 采石场会自行更新)?如果我直接从 BottomLevel class 处理 Handle class 中的事件,它显然有效。但我需要冒泡消息,我想不出任何其他方法,因为 classes 是如何构建的。是否可以使用标准事件处理程序 class 来实现我的想法?如果是这样怎么办?我是否应该像在我提到的其中一个网站上那样自己做一个活动 class?
我参考了这些网站:
What is the preferred way to bubble events?
更新的答案:
如果您想要触发 'Handler',您必须确保 'BottomLevel' 属于传递给处理程序的 'TopLevel' class 的层次结构,这可以通过依赖注入 (DI) 来完成。
如果 'BottomLevel' 实例化它自己的 classes(无 DI),那么它将不知道 'Handler',因此永远不会触发处理程序。
如果您注释掉 DI 设置并取消注释 'BottomLevel' 实例化,您可以看到不同的行为。
class Program
{
static void Main(string[] args)
{
//setup the classes (dependency injection)
TopLevel topLevel = new TopLevel();
MiddleLevel middleLevel = new MiddleLevel(topLevel);
BottomLevel bottomLevel = new BottomLevel(middleLevel);
//set up the handler
Handler h = new Handler(topLevel);
//using this will not link to 'Handler' as there is no relation between this bottom and top
//BottomLevel bottomLevel = new BottomLevel();
//trigger the bottom class
bottomLevel.TriggerBottom();
//or
bottomLevel.DoSomething(null, "call from main");
Console.ReadLine();
}
}
public class Handler
{
TopLevel _topLevel;
public Handler(TopLevel topLevel)
{
if (topLevel != null)
_topLevel = topLevel;
_topLevel.Message += _topLevel_Message;
}
private void _topLevel_Message(object sender, string e)
{
Console.WriteLine($"handler triggered : {e}");
}
}
public class TopLevel
{
public event EventHandler<string> Message;
public TopLevel()
{ }
public void TriggerTop()
{
Message?.Invoke(this, "origin top");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"Do something at top : {e}");
Message?.Invoke(this, e);
}
}
public class MiddleLevel
{
TopLevel _TopLevel;
public event EventHandler<string> Message;
public MiddleLevel(TopLevel topLevel) : this()
{
_TopLevel = topLevel;
}
public MiddleLevel()
{
if (_TopLevel == null)
_TopLevel = new TopLevel();
//subscribe this message to bottom message event method
Message += (s, e) => { _TopLevel.DoSomething(s, e); };
}
public void TriggerMiddle()
{
Message?.Invoke(this, "origin middle");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"do something in middle : {e}");
//invoke the event(s)
Message?.Invoke(sender, e);
}
}
public class BottomLevel
{
MiddleLevel _MidLevel;
public event EventHandler<string> Message;
public BottomLevel(MiddleLevel midLevel) : this()
{
_MidLevel = midLevel;
}
public BottomLevel()
{
if (_MidLevel == null)
_MidLevel = new MiddleLevel();
////here you assign it
Message += (s, e) => { _MidLevel.DoSomething(s, e); };
}
public void TriggerBottom()
{
DoSomething(this, "origin bottom");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"do something at bottom : {e}");
Message?.Invoke(sender, e);
}
}
我想通过 classes 发送消息。我使用了事件并这样做了:
public class TopLevel{
public event EventHandler<string> Message;
public MiddleLevel mid;
public TopLevel()
{
mid.Message += (s, e) => { Message(s, e) };
}
}
public class MiddleLevel{
public event EventHandler<string> Message;
public BottomLevel bottom;
public MiddleLevel()
{
bottom.Message += (s, e) => { Message(s, e) };
}
}
public class BootomLevel{
public event EventHandler<string> Message;
public void DoSomething()
{
Message?.Invoke(this, "I did it.");
}
}
public class Handler{
public void HandleEvent(TopLevel top)
{
top.Message += PrintMessage;
}
public void PrintMessage(object sender, string message)
{
Console.WrteLine(message);
}
}
还尝试将构造函数更改为 lambda 表达式,如下所示:
public class TopLevel{
public event EventHandler<string> Message;
public MiddleLevel mid;
public TopLevel()
{
mid.Message += (s, e) => { Message?.Invoke(s, e); };
}
}
public class MiddleLevel{
public event EventHandler<string> Message;
public BottomLevel bottom;
public MiddleLevel()
{
bottom.Message += (s, e) => { Message?.Invoke(s, e); };
}
}
public class BootomLevel{
public event EventHandler<string> Message;
public void DoSomething()
{
Message?.Invoke(this, "I did it.");
}
}
public class Handler{
public void HandleEvent(TopLevel top)
{
top.Message += PrintMessage;
}
public void PrintMessage(object sender, string message)
{
Console.WrteLine(message);
}
}
以上代码不打印任何消息。即使我在 MiddleLevel class 中处理事件,我仍然没有收到消息。我认为这是因为消息调用是在构造函数中进行的(即使 linq 采石场会自行更新)?如果我直接从 BottomLevel class 处理 Handle class 中的事件,它显然有效。但我需要冒泡消息,我想不出任何其他方法,因为 classes 是如何构建的。是否可以使用标准事件处理程序 class 来实现我的想法?如果是这样怎么办?我是否应该像在我提到的其中一个网站上那样自己做一个活动 class?
我参考了这些网站:
What is the preferred way to bubble events?
更新的答案:
如果您想要触发 'Handler',您必须确保 'BottomLevel' 属于传递给处理程序的 'TopLevel' class 的层次结构,这可以通过依赖注入 (DI) 来完成。
如果 'BottomLevel' 实例化它自己的 classes(无 DI),那么它将不知道 'Handler',因此永远不会触发处理程序。
如果您注释掉 DI 设置并取消注释 'BottomLevel' 实例化,您可以看到不同的行为。
class Program
{
static void Main(string[] args)
{
//setup the classes (dependency injection)
TopLevel topLevel = new TopLevel();
MiddleLevel middleLevel = new MiddleLevel(topLevel);
BottomLevel bottomLevel = new BottomLevel(middleLevel);
//set up the handler
Handler h = new Handler(topLevel);
//using this will not link to 'Handler' as there is no relation between this bottom and top
//BottomLevel bottomLevel = new BottomLevel();
//trigger the bottom class
bottomLevel.TriggerBottom();
//or
bottomLevel.DoSomething(null, "call from main");
Console.ReadLine();
}
}
public class Handler
{
TopLevel _topLevel;
public Handler(TopLevel topLevel)
{
if (topLevel != null)
_topLevel = topLevel;
_topLevel.Message += _topLevel_Message;
}
private void _topLevel_Message(object sender, string e)
{
Console.WriteLine($"handler triggered : {e}");
}
}
public class TopLevel
{
public event EventHandler<string> Message;
public TopLevel()
{ }
public void TriggerTop()
{
Message?.Invoke(this, "origin top");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"Do something at top : {e}");
Message?.Invoke(this, e);
}
}
public class MiddleLevel
{
TopLevel _TopLevel;
public event EventHandler<string> Message;
public MiddleLevel(TopLevel topLevel) : this()
{
_TopLevel = topLevel;
}
public MiddleLevel()
{
if (_TopLevel == null)
_TopLevel = new TopLevel();
//subscribe this message to bottom message event method
Message += (s, e) => { _TopLevel.DoSomething(s, e); };
}
public void TriggerMiddle()
{
Message?.Invoke(this, "origin middle");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"do something in middle : {e}");
//invoke the event(s)
Message?.Invoke(sender, e);
}
}
public class BottomLevel
{
MiddleLevel _MidLevel;
public event EventHandler<string> Message;
public BottomLevel(MiddleLevel midLevel) : this()
{
_MidLevel = midLevel;
}
public BottomLevel()
{
if (_MidLevel == null)
_MidLevel = new MiddleLevel();
////here you assign it
Message += (s, e) => { _MidLevel.DoSomething(s, e); };
}
public void TriggerBottom()
{
DoSomething(this, "origin bottom");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"do something at bottom : {e}");
Message?.Invoke(sender, e);
}
}