我会承认,我正在做作业而且我坚持这一个问题(A部分)。我如何通过通知方法作为铁路信号的参考?我能不能找出在抽象构造函数中调用哪个类,然后在notify方法中打印类名?例如:
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)
}
}
答案 0 :(得分:2)
这种代码/设计存在缺陷,因为它的作用是RailwayUser
,将对象引用注册到_watchers
类中的RailWaySignal
列表,后者又调用公共调用Notice
时每个用户的Notify
方法,而不是Event Signaling
或Function Pointer
的工作方式。实际上公共_watchers
是危险的,因为它可以被任何用户清除,尽管可以使用属性访问来审核
问题代码
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
以下是使用事件和代表的实际代码:
正确版本
在线代码段 - 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, Colour e)
,它有助于将相关信息传递给被调用的RailwayUser
,我们现在知道RailwaySignal触发了对RailwayUser的通知及其颜色值RailwayUser
是一个非抽象类Notify()
内的RailwaySignal
方法执行事件,我们在TestNotification()
内使用RailwayUser
人工调用它仅用于演示目的,但理想情况下它应在内部触发并且应该传递像Color Func
,Action
之类的预定义代理经常用于类似的通知机制,它们在内部使用类似的机制,虽然声明一个明确的event
,它在内部是{{ 1}}是一个定义良好的模式,特别是对于Ui控件delegate
,其中object sender, EventArgs e
可以将事件执行者(RailwaySignal)中的所有信息包装到事件接收者(RailwayUser)答案 1 :(得分:1)
它看起来像一个Observer模式。您可以将从RailwayUser
对象实例继承的SubClass传递给RailwaySignal
类
您的RailwayUser
课程需要创建public abstract void Notice(Colour state)
方法。
public abstract class RailwayUser
{
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.WriteLine(className);
}
public abstract void Notice(Colour state);
}
Driver
类可以继承RailwayUser
类,然后覆盖通知方法。
public class Driver : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine($"Driver see the {state.ToString()}");
}
}
有
List<RailwayUser> _watches
包含可观察对象SubScript(RailwayUser user)
列表中使用_watches
订阅用户。Notify()
调用所有可观察的Notify方法。 看起来像这样。
public class RailwaySignal
{
private List<RailwayUser> _watches;
public Colour Stata { get; set; }
public RailwaySignal()
{
_watches = new List<RailwayUser>();
}
public void SubScript(RailwayUser user)
{
_watches.Add(user);
}
public void Notify()
{
foreach (RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(Stata);
}
}
}
样品:https://dotnetfiddle.net/GcdGMy
您还可以使用event
将方法传递到RailwaySignal
,然后调用Notify
方法。
public enum Colour
{
Green,
Red,
Disable
}
public abstract class RailwayUser
{
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.WriteLine(className);
}
public abstract void Notice(Colour state);
}
public class Driver : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine("Driver see the "+ state.ToString());
}
}
public class Controller : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine("Controller see the " + state.ToString());
}
}
public class RailwaySignal
{
public delegate void NoticeEvent(Colour state);
public event NoticeEvent Notifys;
public Colour Stata { get; set; }
public void Notify()
{
if (Notifys != null)
{
Notifys(Stata);
}
}
}
像这样使用。
RailwaySignal railway = new RailwaySignal() { Stata = Colour.Green};
railway.Notifys += new Driver().Notice;
railway.Notifys += new Controller().Notice;
railway.Notify();