如何在Silverlight 4中简化WCF调用

时间:2011-08-19 09:51:30

标签: c# .net wcf silverlight-4.0 delegates

在Silverlight 4中,从UI线程发出的所有WCF调用必须是异步的。这可以。 WCF客户端代码公开方法和事件,如

void GetDataAsync(SomeArgument a);
event EventHandler<GetDataCompletedEventArgs> GetDataCompleted;

是否可以将其包装或配置W​​CF / Silverlight以生成以下内容?

void GetDataAsync(SomeArgument a, EventHandler<GetDataCompletedEventArgs>);

在我的项目中,我创建了一个负责所有方法调用的类,可以访问更高层(如视图模型)。它公开了如下方法:

void GetData(SomeArgument a, Action<SomeResult> callback);

现在serviceClient可重复使用,因此我需要在呼叫结束后取消订阅* Completed事件。到目前为止,我最好的方法是:

EventHandler<T> MakeHandler<T>(Action<T> callback) where T : AsyncCompletedEventArgs
{
    return (sender, eventArgs) =>
    {
        callback(eventArgs); // perform some operations in view model
        ((Action)eventArgs.UserState)(); // this is to unsubscribe from event
    };
}

void GetData(SomeArgument a, Action<SomeResult> callback)
{
    var handler = MakeHandler<GetDataCompletedEventArgs>((s, ea) => callback(ea.Result));
    serviceClient.GetDataCompleted += handler
    serviceClient.GetDataAsync(a, new Action(() => serviceClient.GetDataCompleted -= handler));
}

我真的想避免为每个使用过的WCF方法重新键入整个GetData()连接,并执行以下操作:

void GetData(SomeArgument a, Action<SomeResult> callback)
{
    serviceClient.GetDataAsync(a, callback);
}

1 个答案:

答案 0 :(得分:3)

您可以使用ServiceClient的Service接口访问WCF服务的开始/结束“.NET异步模式”。例如,如果您有一个名为“Service1”的WCF服务,您的Silverlight项目将包含一个“Service1Client”类(使用Async / Event模式来公开操作),但它还显式实现了一个名为“Service1”的接口,它使用了Begin /每个操作的结束对。使用: -

Service1 service = new Service1Client();

现在可以访问Begin / End对,事情变得容易一些。您可以使用以下通用函数来创建调用异步模式的基本管道:

    public static Action<Action<T>, Action<Exception>> AsyncExecute<T>(Action<AsyncCallback> begin, Func<IAsyncResult, T> end)
    {
        return (success, fail) =>
        {
            AsyncCallback cb = (ar) =>
            {
                try
                {
                    success(end(ar));
                }
                catch (Exception err)
                {
                    fail(err);
                }
            };

            begin(cb);
        };
    }

您可以使用特定功能使用它:

 void GetData(SomeArgument a, Action<SomeResult> success)
 {
      var fn = AsyncExecute<SomeResult>(cb => service.BeginGetData(a, cb, null), service.EndGetData);
      fn(success, GeneralFail);
 }

 public static void GeneralFail(Exception err)
 {
      // General reporting of fail
 }