C#共享逻辑和重用代码的最佳方式
给定函数返回一个KPI值,首先检查缓存,然后执行逻辑,缓存结果并返回一个值,处理故障条件 如何最好地重用缓存、错误处理逻辑。我本质上想要创建的是一个函数,它只执行必要的逻辑,将锅炉板代码抽象出来,并在多个类似函数之间重复使用C#共享逻辑和重用代码的最佳方式,c#,code-reuse,C#,Code Reuse,给定函数返回一个KPI值,首先检查缓存,然后执行逻辑,缓存结果并返回一个值,处理故障条件 如何最好地重用缓存、错误处理逻辑。我本质上想要创建的是一个函数,它只执行必要的逻辑,将锅炉板代码抽象出来,并在多个类似函数之间重复使用 public static int CurrentEmployees() { if (HttpRuntime.Cache["CurrentEmployees"] == null) { try {
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,对这类解决方案要小心(例如,将函数作为参数传递)——它们往往会增长,并且较难维护,例如,抽象基类和派生方法。我真的不同意这一点。在这种情况下,它至少是一个静态方法
,因此不会受到继承的影响