Search code examples
c#code-reuse

C# Best way to share logic and re-use code


The given function returns a KPI value, first it checks its cache, then it performs its logic, caches the result and returns a value, handling a failure condition.

How am I best to re-use the caching, error handling logic. What I essentially want to create is a function that just performs the necessary logic with boiler plate code abstracted away and re-used across multiple similar functions.

public static int CurrentEmployees()
 {
     if (HttpRuntime.Cache["CurrentEmployees"] == null)
     {
         try
         {
             int CurrentEmployees = Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now);
             HttpRuntime.Cache.Insert("CurrentEmployees", CurrentEmployees, null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));

             return CurrentEmployees;
         }
         catch(Exception e)
         {
             //TODO: Report this
             return -1;
         }
     }
     else
         return (int)HttpRuntime.Cache["CurrentEmployees"];
 }

As the boilerplate code is wrapped around the logic it is difficult for me to simply push these into other function calls.


Solution

  • Here's how you could create a generic method to cache whatever you want and reuse this logic.

    public static T Cache<T>(string key, Func<T> loadFunction, Func<T> errorHandler)
    {
         if (HttpRuntime.Cache[key] == null)
         {
             try
             {
                 T value = loadFunction();
             HttpRuntime.Cache.Insert(key, value , null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));
                 return value;
             }
             catch(Exception e)
             {
                 //TODO: Report this
                 return errorHandler();
             }
         }
         else
             return (T)HttpRuntime.Cache[key];
    }
    

    Usage:

    public static int CurrentEmployees()
    {
        return Cache<int>("CurrentEmployees", 
            () => Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now),
            () => -1);
    }