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 分别进行处理。因此,当您像这样添加另一个功能时,您不必更改缓存功能。
给定函数 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 分别进行处理。因此,当您像这样添加另一个功能时,您不必更改缓存功能。