2015-07-10 2 views
1

Данная функция возвращает значение KPI, сначала проверяет его кеш, затем выполняет свою логику, кэширует результат и возвращает значение, обрабатывая условие сбоя.C# Лучший способ обмена логикой и повторного использования кода

Как я могу лучше использовать кэширование, логику обработки ошибок. То, что я, по сути, хочу создать, - это функция, которая просто выполняет необходимую логику с отобранным кодовым таблицей и повторно используется через несколько подобных функций.

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

Как шаблонного кода оборачивают вокруг логики это трудно для меня, чтобы просто нажать их в другие вызовы функций.

+0

Общая часть может входить в отдельный метод (иногда общий), отдельная часть либо передается в качестве параметров, либо делегируется, либо после выполнения (после вызова метода). Как выглядит другая функция? Назначение нового значения (в случае его отсутствия) может быть делегировано и добавлено с помощью lamda, а имя передается как параметр. – Sinatr

+0

Мне кажется, что вы, вероятно, должны использовать [полиморфизм] (https://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29). Это широкая тема, хотя .. И зависит от вашей настройки. Не могли бы вы объяснить, что вы пробовали, и почему это не сработало? – Default

ответ

3

Вот как вы могли бы создать общий метод для кэширования того, что вы хотите, и повторно использовать эту логику.

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); 
} 
+0

вы можете добавить такой же общий помощник для обработки исключений, принимая функцию для вызова исключения в качестве первого аргумента и реальной функции как второй аргумент. Затем используйте его для переноса функции, переданной в оболочку кэша. Таким образом, в кеше не будет логики обработки ошибок. –

+0

не уверен, что вы имеете в виду. не стесняйтесь публиковать свой собственный ответ, чтобы показать, что вы имеете в виду. – DLeh

+0

хорошо согласен с вашим ответом, это просто, что кэш в вашем примере имеет две обязанности - кэширование и обработку ошибок, и вы можете переписать его, чтобы следовать «единой ответственности». Что-то вроде этого: 'return Cache (« CurrentEmployees »,() => Ошибка (() => -1,() => Employee.Load())); } ' –

0

Согласен с answer from @DLeh, но я бы написать так:

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? 
    } 
} 

Таким образом, мы отделяем логику кэширования от обработка ошибок (f принцип единственной ответственности) и могут повторно использовать/составлять каждый отдельно. Поэтому, когда вы добавляете другую функцию, подобную этой, вам не придется менять функцию кеширования.

Смежные вопросы