2010-04-15 79 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); 
} 

回答

2

,通常與完成看點面向對象編程和據我所知目前,在這個功能的.NET框架(或C#)中不支持。請參閱this post

此外,據我所知 - 沒有自己做任何測試 - 似乎frameworks提供AOP功能基於ContextBoundObject類的.NET會招致很多性能開銷,所以你可能希望考慮當決定易用性的優點是否大於性能劣勢。

+0

是的,我想到了AOP,但有時候開始使用它有點讓人望而生畏。在C#中的AOP的一些開源框架:http://csharp-source.net/open-source/aspect-oriented-frameworks – AaronLS 2010-04-15 14:35:55

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,很好的例子(本身有趣的模式) – 2010-04-15 15:37:17

相關問題