C#代表v.s.事件处理程序
我想在陷阱发生时向所有订户发送警报消息 我创建的代码使用委托方法C#代表v.s.事件处理程序,c#,delegates,event-handling,observer-pattern,C#,Delegates,Event Handling,Observer Pattern,我想在陷阱发生时向所有订户发送警报消息 我创建的代码使用委托方法myDelegate可以很好地工作 我的问题是: 我想知道是否最好使用EventHandler而不是委托? 在我的例子中,我不确定委托和EventHandler之间有什么区别 notify(trapinfot),这就是我在这里获取陷阱信息所做的。但这似乎不是一个好主意。我读了一些在线教程,介绍如何传递代理对象;我想知道这对我来说是否合适?我该怎么做呢?有什么建议吗 非常感谢:) 我的代码: public class trapinfo
myDelegate
可以很好地工作
我的问题是:
EventHandler
而不是委托?
在我的例子中,我不确定委托和EventHandler
之间有什么区别notify(trapinfot)
,这就是我在这里获取陷阱信息所做的。但这似乎不是一个好主意。我读了一些在线教程,介绍如何传递代理对象;我想知道这对我来说是否合适?我该怎么做呢?有什么建议吗public class trapinfo
{
public string info;
public string ip;
public string cause;
}
public class trap
{
public delegate void myDelegate(trapinfo t);
public myDelegate del;
trapinfo info = new trapinfo();
public void run()
{
//While(true)
// If a trap occurred, notify the subscriber
for (; ; )
{
Thread.Sleep(500);
foreach (myDelegate d in del.GetInvocationList())
{
info.cause = "Shut Down";
info.ip = "192.168.0.1";
info.info = "Test";
d.Invoke(info);
}
}
}
}
public class machine
{
private int _occuredtime=0;
public trapinfo info = new trapinfo();
public void notify(trapinfo t)
{
++_occuredtime;
info.cause = t.cause;
info.info = t.info;
info.ip = t.ip;
getInfo();
}
public void subscribe(trap t)
{
t.del += new trap.myDelegate(notify);
}
public void getInfo()
{
Console.WriteLine("<Alert>: cauese/{0}, info/ {1}, ip/{2}, time/{3}",
info.cause, info.info, info.ip,_occuredtime);
}
}
class Program
{
static void Main(string[] args)
{
trap t = new trap();
machine machineA = new machine();
machineA.subscribe(t);
t.run();
}
}
public class TrapInfoEventArgs : EventArgs
{
public int info { get; set; }
public string ip { get; set; }
public string cause { get; set; }
}
public class trap
{
public event EventHandler<TrapInfoEventArgs> TrapOccurred;
protected virtual void OnTrapOccurred(TrapInfoEventArgs e)
{
EventHandler<TrapInfoEventArgs> handler = TrapOccurred;
if (handler != null)
{
handler(this, e);
}
}
public void run()
{
//While(true)
// If a trap occurred, notify the subscriber
for (; ; )
{
Thread.Sleep(500);
TrapInfoEventArgs args = new TrapInfoEventArgs();
args.cause = "Shut Down";
OnTrapOccurred(args);
}
}
}
public class machine
{
public void c_TrapOccurred(object sender, TrapInfoEventArgs e)
{
Console.WriteLine("<Alert>: cauese/{0}, info/ {1}, ip/{2}, time/{3}",
e.cause, e.info, e.ip, DateTime.Now.ToString());
}
}
class Program
{
static void Main(string[] args)
{
trap t = new trap();
machine machineA = new machine();
t.TrapOccurred += machineA.c_TrapOccurred; //notify machine A
t.run();
}
}
对于您的示例,最好使用
事件
- Visual Studio窗体和WPF设计器可以理解
事件,因此您可以使用IDE订阅事件
- 当引发
,您无需编写自己的事件时
处理来迭代它们foreach
是大多数程序员希望访问此功能的方式事件
- 如果使用委托,消费代码可能会以您希望防止的方式(例如重置其调用列表)干扰委托<代码>事件不允许发生这种情况
事件
可以创建一个从EventArgs
派生的类来保存数据,并在引发数据时将其传递给事件。消费者将可以访问它
有关详细信息,请参见此处:事件和委托的区别在于: 事件声明在委托实例上添加了一层保护。 此保护可防止委托的客户端重置 委托及其调用列表,仅允许添加或删除 调用列表中的目标 看 2) 在我看来,您的订户不应该随意更改代理。一个订户可以将
=
分配给它,而不是添加+=
。这将分配一个新的委托,因此,前一个委托及其调用列表将丢失,并且不再调用前一个订阅服务器。所以你应该使用Event。或者,您可以更改代码,使您的委托成为私有的,并编写额外的函数对其进行操作,以定义您自己的事件行为
//preventing direct assignment
private myDelegate del ;
public void AddCallback(myDelegate m){
del += m;
}
public void RemoveCallback(myDelegate m){
del -= m;
}
//or
public static trap operator +(trap x,myDelegate m){
x.AddCallback(m);
return x;
}
public static trap operator -(trap x, myDelegate m)
{
x.RemoveCallback(m);
return x;
}
//usage
//t.AddCallback(new trap.myDelegate(notify));
t+=new trap.myDelegate(notify);
所以我必须在我发布的代码中处理调用列表,是吗?您需要提供函数来更改它,而不是直接访问它。OOP封装概念可能重复