我承认,我正在做作业,但我被困在这个问题上(A 部分)。我如何通过通知方法作为铁路信号的引用?我不能只找出在抽象构造函数中调用了哪个类,然后在通知方法中打印类名吗?例如:
铁路用户
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.Writeline(className);
}
铁路信号类
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
最佳答案
这种代码/设计是有缺陷的,因为它所做的是RailwayUser
,将对象引用注册到RailWaySignal
中的_watchers
列表> 类,当 Notify
被调用时,它依次调用每个用户的公共(public) Notice
方法,这不是 Event Signaling
或 的方式函数指针
有效。事实上 public _watchers
是危险的,因为它可以被任何用户清除,尽管可以使用属性访问来调节
有问题的代码
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
以下是使用事件和委托(delegate)的实际代码:
正确版本
在线代码片段 - https://www.jdoodle.com/embed/v0/uEc
void Main()
{
List<RailwayUser> railwayUsers = new List<RailwayUser>();
railwayUsers.Add(new RailwayUser());
railwayUsers.Add(new RailwayUser());
RailwayUser.TestNotification();
}
public enum Colour
{
Red,
Green,
NoSignal
}
public class RailwaySignal
{
public string Name {get; set;}
public RailwaySignal(string railwaySignalName)
{
Name = railwaySignalName;
}
// Delegate for handling event
public delegate void RailwaySignalEventHandler(object source, Colour e);
// Delagate object for handling event
private RailwaySignalEventHandler _railwaySignalEvent;
// Event Accessor
public event RailwaySignalEventHandler RailwaySignalEvent
{
add
{
lock (this)
{
_railwaySignalEvent += value;
}
}
remove
{
lock (this)
{
_railwaySignalEvent -= value;
}
}
}
// Invoke Event for subscribed clients
private void Notify()
{
if (_railwaySignalEvent != null)
_railwaySignalEvent.Invoke(this, Colour.Green);
}
// Test the Event Invocation
public void TestEvent()
{
Notify();
}
}
public class RailwayUser
{
private static RailwaySignal railwaySignal { get; set;} = new RailwaySignal("Signal1");
public RailwayUser()
{
railwaySignal.RailwaySignalEvent += this.Notice;
}
public static void TestNotification()
{
railwaySignal.TestEvent();
}
public void Notice(object sender, Colour color)
{
Console.WriteLine($"Notice Called, Colour is :: {color}, Sender is :: {((RailwaySignal)sender).Name}");
}
}
结果
Notice Called, Colour is :: Green, Sender is :: Signal1
Notice Called, Colour is :: Green, Sender is :: Signal1
重要细节
- 事件的签名是
(object source, Color e)
,它有助于将相关信息传递给调用的RailwayUser
,我们现在知道 RailwaySignal 触发了通知 RailwayUser 及其颜色值 - 事件/委托(delegate)与被调用方法具有相同的签名(这是委托(delegate)/函数指针工作的基础)
- 为了简化,
RailwayUser
是一个非抽象类 - 事件是使用
RailwaySignal
中的Notify()
方法执行的,我们在RailwayUser 中使用
仅用于演示目的,但理想情况下应在内部触发并传递当前状态,如颜色TestNotification()
人为地调用它 - 像
Func
、Action
这样的预定义委托(delegate)经常用于类似的通知机制,它们在内部使用类似的机制工作,尽管声明了一个显式的event
在内部是一个delegate
是一个定义良好的模式,尤其是对于 Ui 控件 - .Net 框架公开的标准事件具有签名
object sender, EventArgs e
,其中EventArgs
可以包装从Event executor (RailwaySignal) 到Event receiver (铁路用户)
关于c# - 如何传递抽象方法作为引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50195538/