2010-04-15 12 views
5

Zastanawiam się, czy istnieje sposób napisania metody lub klasy, która dodaje do dowolnej metody kod dzielony między wiele metod. Metody zwracają różne rzeczy, a niektóre z nich są po prostu nieważne.Czy istnieje sposób użycia jednej metody postępowania z innymi, aby uniknąć powielania kodu?

Poniżej znajduje się część kodu, który jest powielony w metodach.

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

Każda pomoc zostanie bardzo doceniona.


Nix rozwiązanie zastosowano w kodzie powyżej

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

Odpowiedz

5

I rzeczywiście miał ten sam problem ....

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

To się zwykle wykonaną ze wskazaniem Programowanie zorientowane i o ile wiem, że W tej chwili nie ma wsparcia dla platformy .NET (lub C#) dla tej funkcji. Zobacz this post.

Ponadto, o ile mogę zrozumieć - bez zrobiwszy każdy testuje się - wydaje się, że frameworks które zapewniają AOP wyposażony do .NET oparte na klasie ContextBoundObject ponieść dużo napowietrznych wydajności można więc uznać, że kiedy podejmowanie decyzji, czy korzyść z łatwości użytkowania jest większa niż wada wydajności.

+0

Yeh, myślałem o AOP, ale że jest czasami trudne zacząć używać dla niektórych. Niektóre frameworki open source dla AOP w C#: http://csharp-source.net/open-source/aspect-oriented-frameworks – AaronLS

1

Możesz użyć delegatów i ogólnych delegatów, takich jak public delegate T Func<T>();, aby przekazać kod do pakowania. W poniższym przykładzie potrzebowałem czegoś podobnego, gdy chciałem, aby moja logika ponownej próby była ponownie wykorzystywana w wielu scenariuszach. Na przykład na początku widać, jak ten używany jest do przekazywania w moich anonimowych delegatów:

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, ładny przykład (ciekawy wzór sam w sobie) –

Powiązane problemy