What is the best workaround for the WCF client `using` block issue?

前端 未结 26 1703
余生分开走
余生分开走 2020-11-22 00:03

I like instantiating my WCF service clients within a using block as it\'s pretty much the standard way to use resources that implement IDisposable:

相关标签:
26条回答
  • 2020-11-22 00:37

    @Marc Gravell

    Wouldn't it be OK to use this:

    public static TResult Using<T, TResult>(this T client, Func<T, TResult> work)
            where T : ICommunicationObject
    {
        try
        {
            var result = work(client);
    
            client.Close();
    
            return result;
        }
        catch (Exception e)
        {
            client.Abort();
    
            throw;
        }
    }
    

    Or, the same thing (Func<T, TResult>) in case of Service<IOrderService>.Use

    These would make returning variables easier.

    0 讨论(0)
  • 2020-11-22 00:37

    My method of doing this has been to create an inherited class that explicitly implements IDisposable. This is useful for folks who use the gui to add the service reference ( Add Service Reference ). I just drop this class in the project making the service reference and use it instead of the default client:

    using System;
    using System.ServiceModel;
    using MyApp.MyService; // The name you gave the service namespace
    
    namespace MyApp.Helpers.Services
    {
        public class MyServiceClientSafe : MyServiceClient, IDisposable
        {
            void IDisposable.Dispose()
            {
                if (State == CommunicationState.Faulted)
                {
                    Abort();
                }
                else if (State != CommunicationState.Closed)
                {
                    Close();
                }
    
                // Further error checks and disposal logic as desired..
            }
        }
    }
    

    Note: This is just a simple implementation of dispose, you can implement more complex dispose logic if you like.

    You can then replace all your calls made with the regular service client with the safe clients, like this:

    using (MyServiceClientSafe client = new MyServiceClientSafe())
    {
        var result = client.MyServiceMethod();
    }
    

    I like this solution as it does not require me to have access to the Interface definitions and I can use the using statement as I would expect while allowing my code to look more or less the same.

    You will still need to handle the exceptions which can be thrown as pointed out in other comments in this thread.

    0 讨论(0)
提交回复
热议问题