C# 共享逻辑和重用代码的最佳方式

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

给定函数 returns 一个 KPI 值,首先它检查它的缓存,然后执行它的逻辑,缓存结果和 returns 一个值,处理失败情况。

我怎样才能最好地重用缓存、错误处理逻辑。我本质上想要创建的是一个函数,它只执行必要的逻辑,将样板代码抽象出来并在多个类似函数中重复使用。

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"];
 }

由于样板代码围绕着逻辑,我很难将它们简单地推送到其他函数调用中。

下面介绍了如何创建通用方法来缓存所需的任何内容并重用此逻辑。

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];
}

用法:

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

同意 但我会这样写:

public static class HelperFunctions
{
    public static Func<T> Cache<T>(this Func<T> inner, string cacheName)
    {
        return () =>
        {
            if (HttpRuntime.Cache[cacheName] == null)
            {
                var result = inner();
                HttpRuntime.Cache.Insert(cacheName, inner(), null, DateTime.Now.AddMinutes(20), new TimeSpan(0, 10, 0));

                return result;
            }

            return (T)HttpRuntime.Cache[cacheName];
        };
    }

    public static Func<T> OnError<T>(this Func<T> inner, Func<Exception, T> onError)
    {
        return () =>
        {
            try
            {
                return inner();
            }
            catch (Exception e)
            {
                return onError(e);
            }
        };
    }
}

用法:

public static class Employees
{
    public static int CurrentEmployees()
    {
        return (new Func<int>(() => Employee.Load().Count(x => x.DateFinished == null && !x.Contractor && x.DateStarted < DateTime.Now)))
            .Cache("CurrentEmployees")
            .OnError(e => -1) 
            ();//TODO: log?
    }
}

通过这种方式,我们将缓存逻辑与错误处理分开(遵循单一责任原则),并且能够 reuse/compose 分别进行处理。因此,当您像这样添加另一个功能时,您不必更改缓存功能。