none
Checking e.UserState in *Completed WCF methods

    Question

  • Hello

    Recently I added a UserState parameter to my *Async() WCF calls. In every *Completed method I have to check if UserState is correct (e.UserState as string is equal to UserState given as *Async() method parameter) in order to continue code execution. 

    [Why I need this? Just to avoid multiple code execution (when many instances of ViewModels subscribes to the same WCF client *completed method - then every single *Async() call from any ViewModel fires code execution of *Completed method in EVERY ViewModel). ]

    So this is my WCF method call: 

    Client.GetDataAsync(parameter,myUserStateString);

    And this is my UserState object checking in *Completed: 

    if(!(e.UserState!=null && e.UserState.ToString().Equals(myUserStateString))) return;

    Now is my question: is it possible to put code responsible for UserState checking in one place? Now I have to put it in every *completed method in every ViewModel (I also have to add extra UserState parameter to every ViewModel's WCF *Async call). 

    OK, I know it's only one line per *Completed method, but I'm just curious if my code can be more elegant.

    Wednesday, December 07, 2011 5:25 PM

Answers

  • Hi. How about something like this:

    public class ServiceWrapper
    {
      public void GetDataAsync(object parameter, Action<object> onFinished)
      {
        // additional code to setup Client and hook events, just like you do now already
        Client.GetDataAsync(parameter,onFinished);
      }
    
      private GetDataAsyncCompleted(object sender, CompletedEventArgs e)
      {
        var onFinishedCallback = e.UserState as Action<object>;
        if (onFinishedCallback != null)
        {
          onFinishedCallback(e.Result);
        }
      }
    }

    The idea is to wrap the logic in a seperate class. You may even be able to make that class static, and of course you can make it more fancy to add error handling and other features, for example change the result type from "object" to the real type. To use that in your view models, you would simply do:

    private ServiceWrapper _service = new ServiceWrapper();
    
    // ...
    // in some method etc.:
    _service.GetDataAsync(someParameter, OnGetDataAsyncCompleted);
    
    // this is called when the service call is done
    private void OnGetDataAsyncCompleted(object result)
    {
      // do something with "result"
    }

    There you go, your view model does not need to do any checks etc. and only is called for its particular own service call, not the others. Again, you might be able to make the wrapper static to avoid the extra field in your view model, and you can change the type of the action/callback to the real type.

     

    Wednesday, December 07, 2011 6:39 PM

All replies

  • Hi. How about something like this:

    public class ServiceWrapper
    {
      public void GetDataAsync(object parameter, Action<object> onFinished)
      {
        // additional code to setup Client and hook events, just like you do now already
        Client.GetDataAsync(parameter,onFinished);
      }
    
      private GetDataAsyncCompleted(object sender, CompletedEventArgs e)
      {
        var onFinishedCallback = e.UserState as Action<object>;
        if (onFinishedCallback != null)
        {
          onFinishedCallback(e.Result);
        }
      }
    }

    The idea is to wrap the logic in a seperate class. You may even be able to make that class static, and of course you can make it more fancy to add error handling and other features, for example change the result type from "object" to the real type. To use that in your view models, you would simply do:

    private ServiceWrapper _service = new ServiceWrapper();
    
    // ...
    // in some method etc.:
    _service.GetDataAsync(someParameter, OnGetDataAsyncCompleted);
    
    // this is called when the service call is done
    private void OnGetDataAsyncCompleted(object result)
    {
      // do something with "result"
    }

    There you go, your view model does not need to do any checks etc. and only is called for its particular own service call, not the others. Again, you might be able to make the wrapper static to avoid the extra field in your view model, and you can change the type of the action/callback to the real type.

     

    Wednesday, December 07, 2011 6:39 PM
  • Thank you, I will try this solution. 

    Friday, December 09, 2011 2:08 AM