2010-04-15 6 views
5

Ich frage mich, ob es eine Möglichkeit gibt, eine Methode oder eine Klasse zu schreiben, die zu irgendeiner Methode einen Code hinzufügen würde, der zwischen vielen Methoden geteilt wird. Die Methoden geben unterschiedliche Dinge zurück und einige von ihnen sind einfach ungültig.Gibt es eine Möglichkeit, eine Methode zu verwenden, um andere zu umgehen, um Code-Duplizierung zu vermeiden?

Unten ist ein Teil des Codes, der in den Methoden dupliziert wird.

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

Jede Hilfe würde sehr geschätzt werden.


Nix Lösung oben auf den Code angewendet

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

Antwort

5

ich das gleiche Problem tatsächlich hatte ....

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

, die normalerweise mit Aspect erreicht ist Orientierte Programmierung und soweit ich weiß th Derzeit gibt es keine Unterstützung im .NET-Framework (oder C#) für diese Funktion. Siehe this post.

Auch soweit ich erfassen konnte - ohne selbst Tests durchgeführt zu haben - scheint es, dass frameworks, die AOP-Funktionen zu .NET basierend auf der ContextBoundObject Klasse bieten eine Menge Leistungs Overhead, so dass Sie dies möglicherweise berücksichtigen möchten die Entscheidung treffen, ob der Vorteil der Benutzerfreundlichkeit größer ist als der Nachteil der Leistung.

+0

Yeh, dachte ich an AOP, aber das entmutigend manchmal zu beginnen, für einige zu verwenden. Einige Open-Source-Frameworks für AOP in C#: http://csharp-source.net/open-source/aspect-orientierte-frameworks – AaronLS

1

Sie können Delegaten und generische Delegaten wie public delegate T Func<T>(); verwenden, um den zu umschließenden Code zu übergeben. Im folgenden Beispiel benötigte ich etwas Ähnliches, bei dem ich meine Wiederholungslogik in vielen Szenarien wiederverwenden wollte. In dem Beispiel am Anfang sehen Sie, wie dies in meinem anonymen Delegierten zu übergeben verwendet wird:

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, nettes Beispiel (ein interessantes Muster an sich) –

Verwandte Themen