当前位置:编程学习 > C#/ASP.NET >>

C#高级程序设计(二)——代理

本质上讲,代理提供了方法的封装,它把方法以某种方式封装在一个代理对象里,通过代理对象来执行调用方法、移除或者添加代理对象等操作。从另一种意义上讲,你可以把代理类型看作单一方法的接口,代理对象看作实现了该接口的对象。
代理对象基础:代理类型
下面的代码定义了一个代理类型
[csharp] 
internal delegate void Feedback(Int32 value); 

C#编译器实际上将这个代理类型转化成为一个继承自MulticastDelegate的类。
[csharp]
internal class Feedback : System.MulticastDelegate  

// Constructor 
public Feedback(Object object, IntPtr method); 
// Method with same prototype as specified by the source code 
public virtual void Invoke(Int32 value); 
// Methods allowing the callback to be called asynchronously 
public virtual IAsyncResult BeginInvoke(Int32 value, 
AsyncCallback callback, Object object); 
public virtual void EndInvoke(IAsyncResult result); 

MulticastDelegate继承自Delegate类,下面是代理类的签名:
[csharp]
public abstract class Delegate : ICloneable, ISerializable 
    { 
        protected Delegate(object target, string method); 
        protected Delegate(Type target, string method); 
 
        public static bool operator !=(Delegate d1, Delegate d2); 
        public static bool operator ==(Delegate d1, Delegate d2); 
 
        public MethodInfo Method { get; } 
        public object Target { get; } 
 
        public virtual object Clone(); 
        public static Delegate Combine(params Delegate[] delegates); 
        public static Delegate Combine(Delegate a, Delegate b); 
        protected virtual Delegate CombineImpl(Delegate d); 
        public static Delegate CreateDelegate(Type type, MethodInfo method); 
        public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure); 
        public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method); 
        public static Delegate CreateDelegate(Type type, object target, string method); 
        public static Delegate CreateDelegate(Type type, Type target, string method); 
        public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure); 
        public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase); 
        public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase); 
        public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure); 
        public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure); 
        public object DynamicInvoke(params object[] args); 
        protected virtual object DynamicInvokeImpl(object[] args); 
        public override bool Equals(object obj); 
        public override int GetHashCode(); 
        public virtual Delegate[] GetInvocationList(); 
        protected virtual MethodInfo GetMethodImpl(); 
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context); 
        public static Delegate Remove(Delegate source, Delegate value); 
        public static Delegate RemoveAll(Delegate source, Delegate value); 
        protected virtual Delegate RemoveImpl(Delegate d); 
    } 

这样的转化实际上定义了代理对象所有可能的操作,下面将一一列出
一、构造并初始化代理对象
最常见的方式是使用下面的方式来构造并初始化代理对象
[csharp]
Feedback fbInstance = new Feedback(new Program().FeedbackToFile); 

然而,随着C#版本的升级,越来越多和代理有关的特性随之引入,同时也改变了代理对象的构造并初始化方式,例如在C#3.0中就可以用匿名方法或者lambda表达式来构造并初始化代理对象。
二、调用代理对象封装的方法
这实际上是调用代理定义时编译器所生成的Invoke或者BeginInvoke方法,一个用于同步调用,另一个用于异步调用。
[csharp] 
fbInstance.Invoke(1);  

但是,C#做了进一步优化,你可以直接通过代理对象来调用其所封装的方法,例如:
[csharp]
fbInstance(1);  

三、连接和移除代理对象
前面看到的代理对象都是封装一个方法,实际上,代理对象可以将一系列方法封装成一个链表,这一特性取决于Delegate类的Combine和Remove方法。
[csharp]
fbChain = (Feedback) Delegate.Combine(fbChain, fb1); 

实际上,C#对这一用法也提供了优化,可以使用+、+=、-、-=运算符来添加或移除代理对象:
[csharp] 
fbChain += fb1;  

代理的扩展:事件
C#事件的引入类似属性的引入,属性是对字段的封装,而事件对象是对代理对象的封装。
当定义如下事件时:
[csharp] 
public event EventHandler<NewMailEventArgs> NewMail; 

C#编译器实际上会将其转换成如下的代码:
[csharp]
// 1. A PRIVATE delegate field that is initialized to null 
private EventHandler<NewMailEventArgs> NewMail = null; 
// 2. A PUBLIC add_Xxx method (where Xxx is the Event name) 
// Allows methods to register interest in the event. 
public void add_NewMail(EventHandler<NewMailEventArgs> value) { 
// The loop and the call to CompareExchange is all just a fancy way 
// of adding a delegate to the event in a thread-safe way 
EventHandler<NewMailEventArgs>prevHandler; 
EventHandler<NewMailEventArgs> newMail = this.NewMail; 
do { 
prevHandler = newMail; 
EventHandler<NewMailEventArgs>newHandler = 
(EventHandler<NewMailEventArgs>) Delegate.Combine(prevHandler, value); 
newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>( 
ref this.NewMail, newHandler, prevHandler); 
} while (newMail != prevHandler); 

// 3. A PUBLIC remove_Xxx method (where Xxx is the Event name) 
// Allows methods to unregister interest in the event. 
public void remove_NewMail(EventHandler<NewMailEventArgs> value) { 
// The loop and the call to CompareExchange is all just a fancy way 
// of removing a delegate from the event in a thread-safe way 
EventHandler<NewMailEventArgs> prevHandler; 
EventHandler<NewMailEventArgs> newMail = this.NewMail; 
do { 
prevHandler = newMail; 
EventHandler<New

补充:软件开发 , C# ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,