Как упростить вызовы WCF в Silverlight 4 - PullRequest
2 голосов
/ 19 августа 2011

В Silverlight 4 все вызовы WCF, сделанные из потока пользовательского интерфейса, должны быть асинхронными.Это отлично.Код клиента WCF предоставляет методы и события, такие как

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

Можно ли обернуть его или настроить WCF / 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));
}

Я бы действительно хотел избежать необходимости перепечатывать всю проводку GetData () для каждого используемого метода WCF и просто делать что-то вроде:

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

1 Ответ

3 голосов
/ 20 августа 2011

Вы можете получить доступ к начальному / конечному шаблону .NET Async для вашей службы WCF, используя интерфейс Service ServiceClient. Например, если у вас есть служба WCF с именем «Service1», ваш проект Silverlight будет содержать класс «Service1Client» (который использует шаблон Async / Event для представления операций), но он также явно реализует интерфейс с именем «Service1», который использует Begin / Конечная пара для каждой операции. Использование: -

Service1 service = new Service1Client();

Теперь с доступом к паре Begin / End все становится немного проще. Вы можете использовать следующую универсальную функцию, чтобы создать базовую систему для вызова шаблона Async:

    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
 }
...