Search code examples
c#wcfrefactoringusing-statement

How to refactor "using" statement to avoid code duplication?


Let's suppose I have the following methods:

 public string GetSchedules(string request)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return soapClient.GetSchedules(AuthenticationInfo, request);
        }
    }

    public string GetCountryList(string request)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return soapClient.GetCountryList(AuthenticationInfo, request);
        }
    }

    public string GetCarriers(string request)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return soapClient.GetCarriers(AuthenticationInfo, request);
        }
    }

As you can see the only different thing is the name of the method invoked. How could I refactor these methods to apply "using" statement only once and avoid code duplication?


Solution

  • To me, what you have is fine, but if you want to factor those out you can use Func and lambdas. Something along these lines:

    public string GetSchedules(string request)
    {
        return Worker((c) => c.GetSchedules(AuthenticationInfo, request));
    }
    
    public string GetCountryList(string request)
    {
        return Worker((c) => c.GetCountryList(AuthenticationInfo, request));
    }
    
    public string GetCarriers(string request)
    {
        return Worker((c) => c.GetCarriers(AuthenticationInfo, request));
    }
    
    private string Worker(Func<SoapClientClassGoesHere, string> f)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return f(soapClient);
        }
    }
    

    Func<A, R> means "a function that takes an argument of type A and returns a value of type R" (and you can have Func<A, B, R> for a function that takes two arguments, etc.).

    More about Func<> and lambdas in this question and this question (and many more, it's a rich topic).

    Here's a live example on ideone.com (a very silly live example, but it demonstrates the concept):

    using System;
    using System.Collections.Generic;
    
    class Foo {
        public string GetSchedules(string request)
        {
            return Worker((c) => c[request]);
        }
    
        public string GetCountryList(string request)
        {
            return Worker((c) => c[request].ToUpper());
        }
    
        public string GetCarriers(string request)
        {
            return Worker((c) => c[request].ToLower());
        }
    
        private string Worker(Func<Dictionary<string,string>, string> f)
        {
            var d = new Dictionary<string, string>();
            d.Add("1", "One");
            d.Add("2", "Two");
            d.Add("3", "Three");
            return f(d);
        }
    }
    
    public class Test
    {
        public static void Main()
        {
            var f = new Foo();
            Console.WriteLine(f.GetSchedules("1"));
            Console.WriteLine(f.GetCountryList("1"));
            Console.WriteLine(f.GetCarriers("1"));
        }
    }