2010-04-15 2 views
5

Интересно, есть ли способ написать метод или класс, которые добавили бы к любому методу некоторый код, который делится между многими методами. Методы возвращают разные вещи, а некоторые из них просто недействительны.Есть ли способ использовать один метод для управления другими, чтобы избежать дублирования кода?

Ниже приведена часть кода, которая дублируется в методах.

StartTimer(MethodBase.GetCurrentMethod().Name); 
try 
{ 
    // Actual method body 
} 
catch (Exception ex) 
{ 
    bool rethrow = ExceptionPolicy.HandleException(ex, "DALPolicy"); 
    if (rethrow) 
    { 
     throw; 
    } 
} 
finally 
{ 
    StopTimer(MethodBase.GetCurrentMethod().Name); 
} 

Любая помощь была бы принята с благодарностью.


решение Никс применяется к коду выше

public T WrapMethod<T>(Func<T> func) 
{ 
    StartTimer(func.Method.Name); 
    try 
    { 
     return func(); 
    } 
    catch (Exception ex) 
    { 
     bool rethrow = ExceptionPolicy.HandleException(ex, "DALPolicy"); 
     if (rethrow) 
     { 
      throw; 
     } 
    } 
    finally 
    { 
     StopTimer(func.Method.Name); 
    } 
    return default(T); 
} 

ответ

5

я на самом деле была эта же проблема ....

C# searching for new Tool for the tool box, how to template this code

public Result<Boolean> CreateLocation(LocationKey key) 
{ 
    LocationDAO locationDAO = new LocationDAO(); 
    return WrapMethod(() => locationDAO.CreateLocation(key)); 
} 


public Result<Boolean> RemoveLocation(LocationKey key) 
{ 
    LocationDAO locationDAO = new LocationDAO(); 
    return WrapMethod(() => locationDAO.RemoveLocation(key)); 
} 


static Result<T> WrapMethod<T>(Func<Result<T>> func) 
{ 
    try 
    { 
     return func(); 
    } 
    catch (UpdateException ue) 
    { 
     return new Result<T>(default(T), ue.Errors); 
    } 
} 
2

Это, как правило, осуществляется с Aspect Ориентированное программирование, и насколько я знаю В настоящее время поддержка .NET Framework (или C#) для этой функции не поддерживается. См. this post.

Кроме того, насколько я мог понять - не сделали ничего испытывать себя - это, кажется, что frameworks, которые предоставляют AOP особенности для .NET на основе ContextBoundObject класса несут много накладных расходов, так что вы, возможно, пожелает рассмотреть вопрос о том, что, когда принимая решение о том, что преимущество простоты использования больше, чем недостаток производительности.

+0

Yeh, я думал, АОП, но что иногда пугающим, чтобы начать использовать для некоторых. Некоторые рамки с открытым исходным кодом для AOP на C#: http://csharp-source.net/open-source/aspect-oriented-frameworks – AaronLS

1

Вы можете использовать делегаты и общие делегаты, такие как public delegate T Func<T>();, чтобы передать в код, который будет обернут. В приведенном ниже примере мне нужно было что-то подобное, когда я хотел, чтобы моя логика повтора использовалась во многих сценариях. В примере в начале вы видите, как это используется, чтобы передать в моих анонимных делегатов:

public class RetryOnError 
{ 
    static void Example() 
    { 
     string endOfLineChar = Environment.NewLine; 
     RetryOnError.RetryUntil<string>(delegate() 
     { 
      //attempt some potentially error throwing operations here 

      //you can access local variables declared outside the the Retry block: 
      return "some data after successful processing" + endOfLineChar; 
     }, 
     new RetryOnError.OnException(delegate(ref Exception ex, ref bool rethrow) 
     { 
      //respond to the error and 
      //do some analysis to determine if a retry should occur 
      //perhaps prompting the user to correct a problem with a retry dialog 
      bool shouldRetry = false; 

      //maybe log error 
      log4net.Error(ex); 

      //maybe you want to wrap the Exception for some reason 
      ex = new Exception("An unrecoverable failure occurred.", ex); 
      rethrow = true;//maybe reset stack trace 

      return shouldRetry;//stop retrying, normally done conditionally instead 
     })); 
    } 

    /// <summary> 
    /// A delegate that returns type T 
    /// </summary> 
    /// <typeparam name="T">The type to be returned.</typeparam> 
    /// <returns></returns> 
    public delegate T Func<T>(); 

    /// <summary> 
    /// An exception handler that returns false if Exception should be propogated 
    /// or true if it should be ignored. 
    /// </summary> 
    /// <returns>A indicater of whether an exception should be ignored(true) or propogated(false).</returns> 
    public delegate bool OnException(ref Exception ex, ref bool rethrow); 

    /// <summary> 
    /// Repeatedly executes retryThis until it executes successfully with 
    /// an exception, maxTries is reached, or onException returns false. 
    /// If retryThis is succesful, then its return value is returned by RetryUntil. 
    /// </summary> 
    /// <typeparam name="T">The type returned by retryThis, and subsequently returned by RetryUntil</typeparam> 
    /// <param name="retryThis">The delegate to be called until success or until break condition.</param> 
    /// <param name="onException">Exception handler that can be implemented to perform logging, 
    /// notify user, and indicates whether retrying should continue. Return of true indicates 
    /// ignore exception and continue execution, and false indicates break retrying and the 
    /// exception will be propogated.</param> 
    /// <param name="maxTries">Once retryThis has been called unsuccessfully <c>maxTries</c> times, then the exception is propagated. 
    /// If maxTries is zero, then it will retry forever until success. 
    /// </param> 
    /// <returns>The value returned by retryThis on successful execution.</returns> 
    public static T RetryUntil<T>(Func<T> retryThis, OnException onException, int maxTries) 
    { 
    //loop will run until either no exception occurs, or an exception is propogated(see catch block) 
    int i = 0; 
    while(true) 
    { 
     try 
     { 
     return retryThis(); 
     } 
     catch (Exception ex) 
     { 
     bool rethrow =false;//by default don't rethrow, just throw; to preserve stack trace 
     if ((i + 1) == maxTries) 
     {//if on last try, propogate exception 
      throw; 
     } 
     else if (onException(ref ex, ref rethrow)) 
     { 
      if (maxTries != 0) 
      {//if not infinite retries 
      ++i; 
      } 
      continue;//ignore exception and continue 
     } 
     else 
     { 
      if (rethrow) 
      { 
      throw ex;//propogate exception 
      } 
      else 
      {//else preserve stack trace 
      throw; 
      } 
     } 
     } 
    } 
    } 

    /// <summary> 
    /// Repeatedly executes retryThis until it executes successfully with 
    /// an exception, or onException returns false. 
    /// If retryThis is succesful, then its return value is returned by RetryUntil. 
    /// This function will run infinitly until success or onException returns false. 
    /// </summary> 
    /// <typeparam name="T">The type returned by retryThis, and subsequently returned by RetryUntil</typeparam> 
    /// <param name="retryThis">The delegate to be called until success or until break condition.</param> 
    /// <param name="onException">Exception handler that can be implemented to perform logging, 
    /// notify user, and indicates whether retrying should continue. Return of true indicates 
    /// ignore exception and continue execution, and false indicates break retrying and the 
    /// exception will be propogated.</param> 
    /// <returns></returns> 
    public static T RetryUntil<T>(Func<T> retryThis, OnException onException) 
    { 
    return RetryUntil<T>(retryThis, onException, 0); 
    } 
} 
+0

+1, хороший пример (интересный образец сам по себе) –

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