关于反射:
http://expert.csdn.net/Expert/topic/2793/2793089.xml?temp=.6948816

解决方案 »

  1.   

     
     
     
       
     
      
     
    每个.NET 框架开发者都必须非常熟悉委托。委托是一种提供类型安全方法回叫机制的技术,他被.NET 框架的许多部分包括Windows Forms、 ASP.NET Web Forms、线程等等广泛采用。不幸的是,对于许多开发者来说委托难于理解和使用,因为委托要求你的编程语言和CLR特别合作。 一旦你理解了所有的驱使委托运行的合作,大部分程序员仍然发现运行委托很麻烦。原因是语法太奇怪了。看看这个经典的代码行: button1.Click += new EventHandler(button1_Click);在这里button1_Click方法看起来如下:void button1_Click(Object sender, EventArgs e) {// Do something, the button was clicked...}这个代码中的意思是使用按钮控制来登记button1_Click 方法的地址,这样,点击按钮,就调用了该方法。对于大多数程序员来说,构造EventHandler对象只是为了得到button1_Click 方法的地址,这让人感觉相当不习惯。 但是,构造EventHandler对象对于CLR来说是必需的,因为该对象提供一个保证该方法只以类型安全的方式被调用的包装。不幸的是,这是一个大多数程序员并不关心的细节。程序员更愿意采用下列方式编写上述代码:button1.Click += button1_Click;幸运的是,微软C# 2.0编译器中的又大又新的特征之一就是它改进了的委托语法。明白地说,编译器仍然提供原来的委托语法这样你现有的代码不会强迫你对源代码做任何修改就可以继续编译。但是,C# 2.0现在提供了许多语法捷径,你可以随便选择对你有用的一个。我将在本文中阐述所有这些捷径。在我们开始之前我说最后一句话:我将要描述的东西实际上归结为C# “语法糖”(即给予程序员另一种编程方法,这种方法更简洁或者更加类似于某些熟悉的符号,并且不影响形式的表达);CLR并不改变它如何以任何方式支持或者实现委托。另外,我将要描述的是C#细节;微软的其他编译器中 (包括V B.NET)没有一个为它们的下一个版本添加我意识到的任何委托语法捷径。 语法捷径#1: 不需要构造委托对象 就像已经显示的一样,C# 2.0允许你不构造委托对象包装就可以指定回叫方法名。 下面是另外一个例子: class AClass {static void CallbackWithoutNewingADelegateObject() {ThreadPool.QueueUserWorkItem(SomeAsyncTask, 5);}static void SomeAsyncTask(Object o) {Console.WriteLine(o);}}这里,ThreadPool类的静态QueueUserWorkItem方法想要一个到WaitCallback委托对象的引用,而WaitCallback委托对象包含到我的SomeAsyncTask方法的引用。因为C# 2.0 编译器能够在自身上推断出这个,所以它允许我省略构造WaitCallback委托对象的代码,从而使得代码更加易于阅读和理解。当然,当代码编译时,C#编译器确实生成 IL,而IL实际上更新了WaitCallback委托对象——我们正好获得了一条语法捷径。 语法捷径 #2: 不需要定义回叫方法 在上述代码中,回叫方法名SomeAsyncTask被传递到ThreadPool的 QueueUserWorkItem方法处。C# 2.0允许你为行内的回叫方法编写代码,这样在他非常专有的方法内就不必编写了。例如,上述代码可重写如下: class AClass {static void CallbackWithoutNewingADelegateObject() {ThreadPool.QueueUserWorkItem(delegate(Object obj) { Console.WriteLine(obj); },5);}}注意QueueUserWorkItem 方法的第一个“参数”是一个代码块!当C# 编译器看出:期望引用委托对象的地方都使用了委托关键词,编译器就会自动地在类(此处为AClass)中 定义一个新方法。这个方法的命名有点像__AnonymousMethod$00000002,你可以通过在编译器生成的装配上运行ILDasm.exe 来修改它。于是“参数”中的代码就设置在这个定义了的编译器的方法内。(对于你在回叫代码中拥有的语句数或者语句种类则没有限制)实际上,就好像C# 编译器重写了你的代码一样,所以他看起来如下: class AClass {static void CallbackWithoutNewingADelegateObject() {ThreadPool.QueueUserWorkItem(new WaitCallback(__AnonymousMethod$00000002),5);}private static void __AnonymousMethod$00000002(Object obj) {Console.WriteLine(obj);}}匿名方法的原型必须匹配WaitCallback 委托的原型:他返回空并获取一个Object参数。但是,我通过在我代码中的委托关键词之后放置“(Object obj)”来指定参数名。 匿名方法专用一文不值;他禁止任何代码不在访问方法的类型内定义(尽管反射可揭露方法确实存在)。而且,请注意匿名方法是静态的;因为定义它的方法CallbackWithoutNewingADelegateObject也是静态的。这就意味着有可能访问类中的任何静态域或者静态方法。请看范例: class AClass {static String sm_name; // A static fieldstatic void CallbackWithoutNewingADelegateObject() {ThreadPool.QueueUserWorkItem(// The callback code can reference static members.delegate(Object obj) { Console.WriteLine(sm_name+ ": " +obj); }, 5);}}如果CallbackWithoutNewingADelegateObject方法不是静态的,编译器将生成一个非静态的匿名方法,当然,该方法的代码能够访问任何非静态的域和非静态的方法: class AClass {String m_name; // An instance field// An instance methodvoid CallbackWithoutNewingADelegateObject() {ThreadPool.QueueUserWorkItem(// The callback code can reference instance members.delegate(Object obj) { Console.WriteLine(m_name+ ": " +obj); },5);}}
     
     
      

  2.   

    语法捷径#3: 不需要指定回叫方法参数 上述语法捷径的一个常见用法就是你希望点击按钮时执行某些代码: button1.Click += delegate(Object sender, EventArgs e){ MessageBox.Show("The Button was clicked!"); };不用手工实现和定义另一个方法就能够正确制定行内的代码那太好了。但是,在此例中,回叫代码一点也不涉及回叫方法的参数、发送器等等。如果你的回叫代码不在乎参数,C# 允许上述代码缩短成这样: button1.Click += delegate { MessageBox.Show("The Button was clicked!"); };注意我正好从原来的代码中删除了"(Object sender, EventArgs e)" 部分。当编译器发布匿名方法时,他仍然发布原型确切匹配委托的方法——CLR为了类型安全性绝对需要它。在这种情况下,编译器仍然发布匹配EventHandler委托(按钮的点击事件期望的委托类型)的匿名方法。只是参数不被匿名方法的代码访问而已。 如果回叫代码访问任何一个参数,那么你必须在委托关键词之后包括插入语、参数类型和变量名。返回类型仍然可从委托的类型推断出,并且,如果返回类型不为空,你必须在回叫代码中有一个返回语句。 语法捷径 #4: 不需要手动包装类中的局部变量就可以将他们传递给回叫方法 
    我已经说明了回叫代码如何才能访问类中定义的其他成员。但是,有时你可能希望回叫代码访问定义方法中存在的局部参数或者变量。下面是一个不错的例子: class AClass {static void UsingLocalVariablesInTheCallbackCode(Int32 numToDo) {// Some local variablesInt32[] squares = new Int32[numToDo];AutoResetEvent done = new AutoResetEvent(false);// Do a bunch of tasks on other threadsfor (Int32 n = 0; n < squares.Length; n++) {ThreadPool.QueueUserWorkItem(delegate(Object obj) {Int32 num = (Int32) obj; // This task would normally more time consumingsquares[num] = num * num;// If last task, let main thread continue runningif (Interlocked.Decrement(ref numToDo) == 0) done.Set(); }, n);}// Wait for all the other threads to finishdone.WaitOne();// Show the resultsfor (Int32 n = 0; n < squares.Length; n++) Console.WriteLine("Index {0}, Square={1}", n, squares[n]);}}
    这个例子实际上向我们显示了:C# 2.0 使曾经相当复杂的任务的实现变得多么容易。上述方法定义了一个参数:numToDo,和两个局部变量:squares和done。而且,委托回叫代码涉及了这些变量。 现在,假设:回叫代码放置在一个独立的方法内(这个方法曾用作C# 2.0之前的案例)。那么变量值如何传递给回叫方法? 唯一方法就是定义一个新的助手类,它也为每个你想要传递给回叫代码的值定义了一个域。另外,回叫代码不得不被当作该助手类中的一个方法实例来定义。然后, UsingLocalVariablesInTheCallbackCode 方法就不得不构造一个助手类实例,初始化它的局部变量内的值的域,然后构造放进助手对象/实例方法内的委托对象。 这是一件非常单调而且有许多错误倾向的工作,当然C# 2.0 自动为你完成所有的工作。当你编写上面显示的代码时,就好像C# 编译器 重新编写你的代码一样,所以他看起来如下: class AClass {static void UsingLocalVariablesInTheCallbackCode(Int32 numToDo) {// Some local variablesInt32[] squares = new Int32[numToDo];AutoResetEvent done = new AutoResetEvent(false);// Do a bunch of tasks on other threadsfor (Int32 n = 0; n < squares.Length; n++) {// Construct an instance of the helper class__LocalsDisplayClass s$1 = new __LocalDisplayClass();// Initialize fields from the local variable valuess$1.squares = squares;s$1.numToDo = numToDo;s$1.done = done;// New up delegate object bound to the helper object and// its anonymous instance methodThreadPool.QueueUserWorkItem(new WaitCallback(s$1.__anonymousMethod$00000004), n);}// Wait for all the other threads to finishdone.WaitOne();// Show the resultsfor (Int32 n = 0; n < squares.Length; n++) Console.WriteLine("Index {0}, Square={1}", n, squares[n]);}// The helper class is given a strange name to avoid potential// conflicts and is private to forbid access from outside AClassprivate sealed class __LocalsDisplayClass$00000006 : Object {// One public field per local variable used in the callback// codepublic Int32[] squares;public Int32 numToDo;public AutoResetEvent done;// public parameterless constructorpublic __LocalsDisplayClass$00000006 { }// Public instance method containing the callback codepublic void __anonymousMethod$00000004(Object obj) {Int32 num = (Int32) obj;squares[num] = num * num;if (Interlocked.Decrement(ref numToDo) == 0)done.Set();}}}
    总结 C# 2.0 有许多新特征值得炫耀,这些特征非常有用而且极大地增长了程序员的生产力。这些新的委托语法捷径使得委托的使用少了许多烦闷和苦差。小小的方便,如这些语法捷径,为编程添加了乐趣和享受,并将它继续保持下去。[original text] 
    关于作者 Jeffrey Richter是 Wintellect (www.Wintellect.com)的创建者之一;Wintellect 是一家培训、调试和咨询公司,它致力于帮助企业更快更好的构造软件。Jeffrey Richter著有几本最畅销的.NET 和 Win32 编程书,包括Applied Microsoft .NET FrameworkProgramming (微软出版社). Jeffrey也是一名对MSDN Magazine有贡献的编辑,在该杂志上他主持.NET 专栏。Jeff 从1999年10月开始就是微软.NET 框架咨询队伍中的一员,并且从2003年1月开始还加入了微软XML Web服务和通讯咨询队伍("Indigo")。 
      

  3.   

    委托就是对函数的包装,相当于函数指针,不过他是安全的。
    //下面是一个委托和事件的例子
    namespace GMonitor
    {        
             //定义一个代理
    public delegate void ServiceGetCompletedHandler(string host);

             public class ServiceGetThread
    {
    //定义事件
    public event ServiceGetCompletedHandler ServiceGetCompleted; public ServiceGetThread()
    {

                       }
    public void GetServiceList()
    {
                               //执行方法代码.
                               ......
                               //触发事件
    ServiceGetCompleted("你调用了GetServiceList方法");
    }
    }
    }
    =====================================
    在另一个类中使用
    public class MainClass

          private ServiceGetThread sgt = new ServiceGetThread();
          //注册事件
          sgt.ServiceGetCompleted += ServiceGetCompletedHandler(Gerrer);
          
          //事件处理函数
          public void Gerrer(string host)
          {
             //事件触发时处理的函数。
           }
    }
    ///////////
    当sgt.GetServiceList()方法的时候就触发事件了。