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

C#共享逻辑和重用代码的最佳方式,c#,code-reuse,C#,Code Reuse,给定函数返回一个KPI值,首先检查缓存,然后执行逻辑,缓存结果并返回一个值,处理故障条件 如何最好地重用缓存、错误处理逻辑。我本质上想要创建的是一个函数,它只执行必要的逻辑,将锅炉板代码抽象出来,并在多个类似函数之间重复使用 public static int CurrentEmployees() { if (HttpRuntime.Cache["CurrentEmployees"] == null) { try {

给定函数返回一个KPI值,首先检查缓存,然后执行逻辑,缓存结果并返回一个值,处理故障条件

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

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 int CurrentEmployees()
{
if(HttpRuntime.Cache[“CurrentEmployees”]==null)
{
尝试
{
int CurrentEmployees=Employee.Load().Count(x=>x.DateFinished==null&&!x.Contractor&&x.DateStarted

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

以下是如何创建一个通用方法来缓存所需内容并重用此逻辑

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];
}
publicstatict缓存(字符串键、Func-loadFunction、Func-errorHandler)
{
if(HttpRuntime.Cache[key]==null)
{
尝试
{
T值=加载函数();
HttpRuntime.Cache.Insert(key,value,null,DateTime.Now.AddMinutes(20),newtimespan(0,10,0));
返回值;
}
捕获(例外e)
{
//TODO:报告这个
返回errorHandler();
}
}
其他的
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 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?
    }
}
public static int CurrentEmployees()
{
返回缓存(“CurrentEmployees”,
()=>Employee.Load().Count(x=>x.DateFinished==null&&!x.Contractor&&x.datestart -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);
            }
        };
    }
}
公共静态类HelperFunctions
{
公共静态Func缓存(此Func内部,字符串缓存名)
{
return()=>
{
if(HttpRuntime.Cache[cacheName]==null)
{
var结果=内部();
HttpRuntime.Cache.Insert(cacheName,inner(),null,DateTime.Now.AddMinutes(20),newtimespan(0,10,0));
返回结果;
}
return(T)HttpRuntime.Cache[cacheName];
};
}
公共静态函数OnError(此函数内部,函数OnError)
{
return()=>
{
尝试
{
返回内部();
}
捕获(例外e)
{
返回一个错误(e);
}
};
}
}
用法:

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 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?
    }
}
公共静态类员工
{
公共静态int CurrentEmployees()
{
返回(newfunc(()=>Employee.Load().Count(x=>x.DateFinished==null&&!x.Contractor&&x.datestart-1)
();//TODO:日志?
}
}

通过这种方式,我们将缓存逻辑与错误处理分离(遵循单一责任原则),并且能够分别重用/组合每个缓存逻辑。因此,当您添加另一个类似这样的函数时,您不必更改缓存函数。

公共部分可以进入单独的方法(有时是通用的),单个部分可以作为参数传递或委托,也可以在后执行(在方法调用之后)。另一个函数是什么样子的?分配新值(如果缺少)可以委派并使用lamda添加,而名称作为参数传递。在我看来,您可能应该使用。这是一个广泛的话题。。这取决于你的设置。您能解释一下您尝试了什么以及为什么不起作用吗?您可以为异常处理添加相同类型的通用帮助程序,接受函数作为第一个参数调用异常,并将实函数作为第二个参数调用。然后使用它包装传递给缓存包装器的函数。这样缓存将不会有错误处理逻辑。不确定您的意思。我同意你的答案,只是在你的例子中缓存有两个职责——缓存和错误处理,你可以重写它来遵循“单一职责”。类似这样的内容:
returncache(“CurrentEmployees”,()=>Error(()=>-1,()=>Employee.Load());}IMHO,对这类解决方案要小心(例如,将函数作为参数传递)——它们往往会增长,并且较难维护,例如,抽象基类和派生方法。我真的不同意这一点。在这种情况下,它至少是一个
静态方法
,因此不会受到继承的影响