0

I know we can't call an extension method with the same name. But what are the other ways to achieve this? I want to call an extension method which I created to replace an another api method(sealed) which is used by dozen's of classes so making a change in those classes is not feasible. Is there any design pattern or solution which can solve this problem without modifying the existing consumer classes?

Below is the code sample:-

public class RestAppClassThatUsesRestClient
{
    private IRestClient _3rdPartyRestClient;
    private ILogger _logger;
    private IConfiguration _configuration;

    public RestAppClassThatUsesRestClient(IRestClient restClient, ILogger logger, IConfiguration configuration)
    {
        _3rdPartyRestClient = restClient;
        _logger = logger;
        _configuration = configuration;
    }

    public Task<TModel> GetSomething<TModel>(string url)
    {
        return _3rdPartyRestClient.RetryLogic(url);
    }
}

I want to call below static class method without modifying the code in above class which is currently calling the same method from 3rd party library.

/// <summary>
/// Retry logic static class for extending the functionalities of IRestClient client
/// </summary>
public static class RestClientExtentions
{
    public static Task<TModel> RetryLogic(this IRestClient restClient, string url)
    {
        int retryCount = 0;
        int maxRetryAtttemp = configuration.GetSection("AppSettings").GetSection("MaxRetryAttempt").Value;  //maxRetry value need to be set it can be pick from any config file or other sources

        while (retryCount < maxRetryAtttemp)
        {
            try
            {
                return await restClient.Get<TModel>(url);
            }
            catch (System.Net.WebException wex)
            {
                if (retryCount < maxRetryAtttemp)
                {
                    retryCount++;
                    Thread.Sleep(configuration.GetSection("AppSettings").GetSection("Timeout").Value);//time value need to be set it can be pick from any config file or other sources
                }
                else
                {
                    Console.log(_logger.Error(wex));
                    return default(TModel);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        return default(TModel);
    }
}

1 Answers1

0

Your can implement class, wich implementing IRestClient interface and inject to constructor client classes

class RestClientExt : IRestClient {

    private IRestClient _restClient;

    public RestClientExt(IRestClient restFromLib) {

        _restClient = restFromLib;
    }

    public async Task<TModel> Get(string url) 
    {
        int retryCount = 0;
        int maxRetryAtttemp = configuration.GetSection("AppSettings").GetSection("MaxRetryAttempt").Value;  //maxRetry value need to be set it can be pick from any config file or other sources

        while (retryCount < maxRetryAtttemp)
        {
            try
            {
                return await _restClient.Get<TModel>(url);
            }
            catch (System.Net.WebException wex)
            {
                if (retryCount < maxRetryAtttemp)
                {
                    retryCount++;
                    Thread.Sleep(configuration.GetSection("AppSettings").GetSection("Timeout").Value);//time value need to be set it can be pick from any config file or other sources
                }
                else
                {
                    Console.log(_logger.Error(wex));
                    return default(TModel);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        return default(TModel);
    }


    // Other override methods

}


// Next use RestClientExt

IRestClient restClient = new RestClientFromLib();
IRestClient restClientExt = new RestClientExt(restClient);

var client = new RestAppClassThatUsesRestClient(restClientExt, ...)