AutoCallbackServiceAgent基类是一个实现了InvokeAutoCallback方法的简单类,代码如下:
public class AutoCallbackServiceAgent { private object _callbackTarget; public AutoCallbackServiceAgent( object callbackTarget ) { // Store reference to the callback target object. _ callbackTarget = callbackTarget; } protected void InvokeAutoCallback( string methodName, object[] parameters, Type delegateType ) { // Create a delegate of the correct type. Delegate autoCallback = Delegate.CreateDelegate( delegateType, _callbackTarget, methodName ); // If the target is a control, make sure we // invoke it on the correct thread. Control targetCtrl = _callbackTarget as System.Windows.Forms.Control; if ( targetCtrl != null && targetCtrl.InvokeRequired ) { // Invoke the method from the UI thread. targetCtrl.Invoke( autoCallback, parameters ); } else { // Invoke the method from this thread. autoCallback.DynamicInvoke( parameters ); } } }
以上这些代码创建了一个回调函数的委托,并且判断是在调用线程,还是在用户界面线程中调用它。如果调用的目标是一个控件对象,那么它就会在需要的时候从用户界面线程来调用回调函数。
探究这些有趣的细节,如果你仔细的查看代码,你会发现我们可以通过不在基类中指定自动回调委托来进行简化。如果我们不需要对回调委托进行签名,我们就可以几乎自动化的处理所有的事情,把基础的服务代理类简化成只在BeginGetCustomerData方法中实现一行代码。
那我们为什么还要指定这个委托呢?那是因为我们还需要使用Control.Invoke方法。不幸的是.NET Framework的开发者并没有为这一方法提供一个MethodInfo对象,而恰恰是它可以使编写基础代码的工作变得简单许多。
一个替代的办法是指定一个标准的委托类型,把它用于所有的回调函数签名。举例来说,我们可以要求所有的自动回调函数都使用一个方法签名,这个方法签名用来维护原始的对象组,并且向客户端回传Web服务的参数。委托的声明方法如下:
public delegate void AutoCallback( object[] parameters );
使用这个委托我们可以极大地简化服务代理类的代码,但是必须在客户端代码中把返回的数据转换成一定的格式。
这样做值得么?
有必要像上面一样实现一个服务代理类吗?这取决于你想多大程度上简化用户界面开发人员的工作。编写一个如上的服务代理类不一定会减少代码量,但可以使界面开发人员和后台服务开发人员的分工更加明确有效。
除了提供这种简单的异步调用模式外,我们还可以往服务代理类中添加更多的有用功能。以后我会继续在这个思路的基础上加以扩展,向你展示如何在服务代理类上实现诸如自动本地数据缓存等高级功能。在服务代理类上实现这些高级功能意味着用户界面开发人员可以更加轻松的完成工作了。
(编辑:aniston)
|