读书笔记(委托)

委托回调静态方法和实例方法有何区别

  •   当委托绑定静态方法时,内部的对象成员变量_target会被设置成null
  •   当委托绑定实例方法是,_target将会设置成指向该实例方法所属的一个实例对象
  •   当委托被执行时,该对象实例将会用来调用实例方法
 1 class DelegateReturn 
 2     {
 3         public delegate String GetStringDelegate();
 4 
 5         static string GetTypeName() 
 6         {
 7             return typeof(DelegateReturn).ToString();
 8         }
 9         static string GetTimeString()
10         {
11             return DateTime.Now.ToString();
12         }
13         static void TestDelegate() 
14         {
15             GetStringDelegate _myDelegate = new GetStringDelegate(GetTimeString);
16             _myDelegate += GetTypeName;
17 
18             _myDelegate();
19             //1只有一个返回值,GetTypeName返回值
20             foreach (Delegate d in _myDelegate.GetInvocationList())
21                 Console.WriteLine(d.DynamicInvoke());
22             //2会有两个返回值
23         }
24     }

  链式委托的执行顺序是:按照委托链上的顺序从当前委托开始一次往后执行,如果有需要,可以通过GetInvocationList()方法来获得委托链上所有需要执行的委托,并且按照任何希望的顺序去执行它们。

  在上述第二种方法中,委托链中每个方法的返回值都不会丢失

  委托可以是带有返回值的方法,但多于一个带返回值的方法被添加到委托链中时,程序员需要受到地调用委托链上的每个方法,否则委托使用者将只能得到委托链上最后一个被执行方法的返回值

 1  /// <summary>
 2     /// 自定义一个事件类型参数
 3     /// </summary>
 4     public class ConsoleEventArgs : EventArgs 
 5     {
 6         private string _message;
 7         public ConsoleEventArgs():base()
 8         {
 9             _message = String.Empty;
10         }
11         public ConsoleEventArgs(string message) :base() 
12         {
13             _message = message;
14         }
15         public string Message 
16         {
17             get 
18             {
19                 return _message;
20             }
21         }
22     }
23 
24     /// <summary>
25     /// 管理控制台,在输出前发出输出事件
26     /// </summary>
27     public class ConsoleEventManager 
28     {
29         //定义控制台事件成员对象    
30         public event EventHandler<ConsoleEventArgs> ConsoleEvent;
31         /// <summary>
32         /// 控制台输出
33         /// </summary>
34         /// <param name="message">用来构造事件参数</param>
35         public void ConsoleOutput(string message) 
36         {
37             ConsoleEventArgs args = new ConsoleEventArgs(message);
38         }
39         /// <summary>
40         /// 负责发送事件
41         /// </summary>
42         /// <param name="args">事件参数</param>
43         public virtual void SendConsoleEvent(ConsoleEventArgs args) 
44         {
45             //定义一个临时的引用变量,这样可以确保多线程访问时不会发生问题
46             EventHandler<ConsoleEventArgs> temp = ConsoleEvent;
47             if(temp != null)
48             {
49                 temp(this,args);
50             }
51         }
52     }
53     /// <summary>
54     /// 日志类型,订阅控制台输出事件
55     /// </summary>
56     public class Log 
57     {
58         private const String LogFile = "C:\\TestLog.txt";
59         public Log(ConsoleEventManager cm) 
60         {
61             //订阅控制台输出事件
62             cm.ConsoleEvent += WriteLog;
63         }
64         /// <summary>
65         /// 事件处理方法,注意参数固定模式
66         /// </summary>
67         /// <param name="sender">事件发送者</param>
68         /// <param name="args">事件参数</param>
69         private void WriteLog(object sender,EventArgs args) 
70         {
71             if(!File.Exists(LogFile))
72             {
73                 using(FileStream fs = File.Create(LogFile)){}
74             }
75             FileInfo info = new FileInfo(LogFile);
76             using(StreamWriter sw = info.AppendText())
77             {
78                 sw.WriteLine(DateTime.Now.ToString()+"|"+sender.ToString()+"}"+((ConsoleEventArgs)args).Message);
79             }
80         }
81     }
  1. 定义了事件使用的参数类型 ConsoleEventArgs
  2. 定义了事件类型的私有成员 ConsoleEventManager.ConsoleEvent
  3. 定义了事件发送的方法 ConsoleEventManager.SendConsoleEvent
  4. 订阅事件 Log类型

  当程序执行时,ConsoleEventManager类型负责在控制台输出测试字符串,同时,订阅了控制台输出事件的Log类型会在日志文件中写入同样的内容

  事件是一种使用对象或者类能够通过提供通知的成员,客户端可以通过提供事件处理为相应的事件添加可执行代码,事件是一种特殊的委托

  事件是一个委托类型,该委托类型的方法无返回值,并且拥有两个参数,object TEventArg

  事件的订阅和取消都是基于委托链表来实现的

 

 

posted @ 2014-07-31 15:22  sophiadv  阅读(177)  评论(0编辑  收藏  举报