Implementing retry logic for deadlock exceptions - c#

I've implemented a generic repository and was wondering if there is a smart way to implement a retry logic in case of a deadlock exception?
The approach should be the same for all repository methods. So is there anyway I can avoid writing 'try/catch - call method again with retry-count', in every single method?
Any suggetsion are welcome.
A bit of my Repository code:
public class GenericRepository : IRepository
{
private ObjectContext _context;
public List<TEntity> ExecuteStoreQuery<TEntity>(string commandText, params object[] parameters) where TEntity : class
{
List<TEntity> myList = new List<TEntity>();
var groupData = _context.ExecuteStoreQuery<TEntity>(commandText, parameters);
return myList;
}
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return _context.CreateQuery<TEntity>(entityName);
}
public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : class
{
return GetQuery<TEntity>().AsEnumerable();
}
EDIT:
1.Solution:
Modified slightly from chris.house.00's solution
public static T DeadlockRetryHelper<T>(Func<T> repositoryMethod, int maxRetries)
{
var retryCount = 0;
while (retryCount < maxRetries)
{
try
{
return repositoryMethod();
}
catch (System.Data.SqlClient.SqlException ex)
{
if (ex.Number == 1205)// Deadlock
retryCount++;
else
throw;
}
}
return default(T);
}
And you call it like this:
public TEntity FirstOrDefault<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
{
return RetryUtility.DeadlockRetryHelper<TEntity>( () =>p_FirstOrDefault<TEntity>(predicate), 3);
}
protected TEntity p_FirstOrDefault<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
{
return GetQuery<TEntity>().FirstOrDefault<TEntity>(predicate);
}

How about something like this:
public T DeadlockRetryHelper<T>(Func<T> repositoryMethod, int maxRetries)
{
int retryCount = 0;
while (retryCount < maxRetries)
{
try
{
return repositoryMethod();
}
catch (SqlException e) // This example is for SQL Server, change the exception type/logic if you're using another DBMS
{
if (e.Number == 1205) // SQL Server error code for deadlock
{
retryCount++;
}
else
{
throw; // Not a deadlock so throw the exception
}
// Add some code to do whatever you want with the exception once you've exceeded the max. retries
}
}
}
With the above code, your retry logic is all in this method and you can just pass your repository method in as a delegate.

I know this is an old post but wanted to share an updated answer.
EF 6 now has a built-in solution, you can set the execution strategy which would be a one time implementation. You create a class that inherits from DbExectutionStrategy and overrides the ShouldRetryOn() virtual method. You can create a static class of the exceptions containing constant field valuess that are retry eligible codes and loop through each one to determine if the current sql exception being thrown matches the list of eligible retry codes...
public static class SqlRetryErrorCodes
{
public const int TimeoutExpired = -2;
public const int Deadlock = 1205;
public const int CouldNotOpenConnection = 53;
public const int TransportFail = 121;
}
public class MyCustomExecutionStrategy : DbExecutionStrategy
{
public MyCustomExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay) { }
private readonly List<int> _errorCodesToRetry = new List<int>
{
SqlRetryErrorCodes.Deadlock,
SqlRetryErrorCodes.TimeoutExpired,
SqlRetryErrorCodes.CouldNotOpenConnection,
SqlRetryErrorCodes.TransportFail
};
protected override bool ShouldRetryOn(Exception exception)
{
var sqlException = exception as SqlException;
if (sqlException != null)
{
foreach (SqlError err in sqlException.Errors)
{
// Enumerate through all errors found in the exception.
if (_errorCodesToRetry.Contains(err.Number))
{
return true;
}
}
}
return false;
}
}
Finally once, you've set up your custom execution strategy, you simply create another class that inherits from DbConfiguration with a public constructor that Sets the execution strategy:
public class MyEfConfigurations : DbConfiguration
{
public MyEfConfigurations()
{
SetExecutionStrategy("System.Data.SqlClient",() => new MyCustomExecutionStrategy(5,TimeSpan.FromSeconds(10)));
}
}

EntityFramework 6 add ExecutionStrategy feature. All that is need is to setup up the strategy properly.
My retry policy:
public class EFRetryPolicy : DbExecutionStrategy
{
public EFRetryPolicy() : base()
{
}
//Keep this constructor public too in case it is needed to change defaults of exponential back off algorithm.
public EFRetryPolicy(int maxRetryCount, TimeSpan maxDelay): base(maxRetryCount, maxDelay)
{
}
protected override bool ShouldRetryOn(Exception ex)
{
bool retry = false;
SqlException sqlException = ex as SqlException;
if (sqlException != null)
{
int[] errorsToRetry =
{
1205, //Deadlock
-2, //Timeout
};
if (sqlException.Errors.Cast<SqlError>().Any(x => errorsToRetry.Contains(x.Number)))
{
retry = true;
}
}
return retry;
}
}
Tell EF to apply my strategy:
public class EFPolicy: DbConfiguration
{
public EFPolicy()
{
SetExecutionStrategy(
"System.Data.SqlClient",
() => new EFRetryPolicy());
}
}
Sources:
Implementing Connection Resiliency with Entity Framework 6
Microsoft documentation
The retry strategy will not work with user initiated transactions (transaction created with TransactionScope) as explained here. If used you will get the Error The configured execution strategy does not support user initiated transactions

The solution works though I prefer not to have to worry about the number of arguments to the Action or Func that will be retired. If you create a single retry method with a generic Action, you can handle all of the variability of the method to be called in a lambda:
public static class RetryHelper
{
public static void DeadlockRetryHelper(Action method, int maxRetries = 3)
{
var retryCount = 0;
while (retryCount < maxRetries)
{
try
{
method();
return;
}
catch (System.Data.SqlClient.SqlException ex)
{
if (ex.Number == 1205)// Deadlock
{
retryCount++;
if (retryCount >= maxRetries)
throw;
// Wait between 1 and 5 seconds
Thread.Sleep(new Random().Next(1000, 5000));
}
else
throw;
}
}
}
}
Then use it like so:
RetryHelper.DeadlockRetryHelper(() => CopyAndInsertFile(fileModel));

Have you considered some form of policy injection? You could use Unity interception, just as an example, to capture all your repository calls. Then you just write the retry logic once, in the interceptor, rather than repeating it many times in each method.

I have used the below solution provided by MiguelSlv in above post and it worked for me as expected. Its simple and easy.
EntityFramework 6 add ExecutionStrategy feature. All that is need is to setup up the strategy properly.
My retry policy:
public class EFRetryPolicy : DbExecutionStrategy
{
public EFRetryPolicy() : base()
{
}
//Keep this constructor public too in case it is needed to change defaults of exponential back off algorithm.
public EFRetryPolicy(int maxRetryCount, TimeSpan maxDelay): base(maxRetryCount, maxDelay)
{
}
protected override bool ShouldRetryOn(Exception ex)
{
bool retry = false;
SqlException sqlException = ex as SqlException;
if (sqlException != null)
{
int[] errorsToRetry =
{
1205, //Deadlock
-2, //Timeout
};
if (sqlException.Errors.Cast<SqlError>().Any(x => errorsToRetry.Contains(x.Number)))
{
retry = true;
}
}
return retry;
}
}
Tell EF to apply this policy
public class EFPolicy: DbConfiguration
{
public EFPolicy()
{
SetExecutionStrategy(
"System.Data.SqlClient",
() => new EFRetryPolicy());
}
}
Sources:
Implementing Connection Resiliency with Entity Framework 6
Microsoft documentation
The retry strategy will not work with user initiated transactions (transaction created with TransactionScope) as explained here. If used you will get the Error The configured execution strategy does not support user initiated transactions

Related

How to get current retry count while executing using SqlAzureExecutionStrategy

I'm currently using SqlAzureExecutionStrategy to implement retry login in my database transactions.
Here is the custom strategy which is inherited from SqlAzureExecutionStrategy :
using System;
using System.Data.Entity.SqlServer;
using System.Data.SqlClient;
public class DbExecutionStrategy : SqlAzureExecutionStrategy
{
private const int retryCount = 2;
private static readonly TimeSpan maxDelay = TimeSpan.FromMinutes(1);
public DbExecutionStrategy ()
: base(retryCount, maxDelay)
{
}
public DbExecutionStrategy (int maxRetryCount, TimeSpan maxDelay)
: base(maxRetryCount, maxDelay)
{
}
protected override bool ShouldRetryOn(Exception exception)
{
if(exception.InnerException != null && exception.InnerException is SqlException)
{
return true;
}
return false;
}
}
I'm using this custom strategy like :
var executionStrategy = new DbExecutionStrategy();
executionStrategy.Execute(() => { some business logic here });
I want to print the current retry count inside the Execute method. Is it even possible?
This is for the logging purpose. To see which retry yielded best results etc. Please feel free to suggest best retry count and maxDelay before the next retry.
In ShouldRetryOn method, what is the best way to define what are the exceptions you want to retry on? I'm hoping it is switch wth exceptions as cases and retrun true in each case.

EF returns ExecuteReader requires an open and available Connection. The connection's current state is open. error

I have a lot of classes with this structure as you can see:
public class OrganizationUserRepository : IOrganizationUserRepository
{
private DataContext _ctx;
public OrganizationUserRepository(DataContext ctx)
{
_ctx = ctx;
}
public bool Add(OrganizationUser entity)
{
try
{
_ctx.OrganizationUsers.Add(entity);
_ctx.SaveChanges();
return true;
}
catch (Exception ex)
{
// TODO log this error
return false;
}
}
public bool Edit(OrganizationUser entity)
{
try
{
OrganizationUser Edited = _ctx.OrganizationUsers.Where(i => i.Id == entity.Id).First();
_ctx.Entry(Edited).CurrentValues.SetValues(entity);
_ctx.SaveChanges();
return true;
}
catch (Exception ex)
{
// TODO log this error
return false;
}
}
public bool Remove(string id)
{
try
{
Int64 Id = Int64.Parse(id);
OrganizationUser obj = _ctx.OrganizationUsers.Where(i => i.Id == Id).First();
_ctx.OrganizationUsers.Remove(obj);
_ctx.SaveChanges();
return true;
}
catch (Exception ex)
{
// TODO log this error
return false;
}
}
}
The db context in constructor is injected by ninject .as you can see it just one of my classes .and i have multi classes like this in another services that use a single DB .(WCF Service).But i get this error in my wcf tracelog :
ExecuteReader requires an open and available Connection. The connection's current state is open.
I am using EF code first .
I found this Wrap DbContext db = new DbContext() inusing statement. And i want to know should i use this ,if Yes how can i change my class structure to use using in my code ?
I used public Readonly DbContext .i just remove readonly and everything work fine.

Catch derived class Exceptions in base class with different methods and arguments

I'm trying to make something like base "exception handler" thing. So this base class will try-catch exceptions when any method (with any number of parameters) in derived class gets invoked. I'm not good in describing this with words, so here is the scenario:
public abstract BaseClass
{
Exception _ex;
public Exception LastKnownException
{
get
{
return this._ex;
}
}
//...
//what do I do here to assign the value of above property when some random exception occur in derived class?
//...
//The closest I can get...
public void RunMethod(Action method)
{
try
{
method.Invoke();
}
catch (Exception ex)
{
this._ex = ex;
}
}
}
public class DerivedClass : BaseClass
{
public void DoRandomMethod(int couldBeOfAnyTypeHere, bool andIndefiniteNumberOfThese)
{
bool result = false;
var someObject = new OtherClass(couldBeOfAnyTypeHere, out andIndefiniteNumberOfThese);
someObject.DoInternalWork(result); // <-- here is where I need the base class to take care if any exception should occur
}
public int AnotherMethod(int? id)
{
if (!id.HasValue)
id = Convert.ToInt32(Session["client_id"]);
var someOtherObject = new OtherClassB(id.Value);
return someOtherObject.CheckSomething(); // <-- and catch possible exceptions for this one too
}
//The closest I can get... (see base class implementation)
public List<RandomClass> GetSomeListBy(int id)
{
RunMethod(() =>
string[] whateverArgs = new[] { "is", "this", "even", "possible?" };
YetAnotherStaticClass.GetInstance().ExecuteErrorProneMethod(whateverArgs); // <-- Then when something breaks here, the LastKnownException will have something
);
}
}
public class TransactionController : Controller
{
public ActionResult ShowSomething()
{
var dc = new DerivedClass();
dc.DoRandomMethod(30, true);
if (dc.LastKnownException != null)
{
//optionally do something here
return RedirectToAction("BadRequest", "Error", new { ex = dc.LastKnownException });
}
else
{
return View();
}
}
}
EDIT: My simple approach will work, only, I don't want to have to wrap all methods with this lambda-driven RunMethod() method all the time -- I need the base class to somehow intercept any incoming exception and return the Exception object to the derived class without throwing the error.
Any ideas would be greatly appreciated. And thanks in advance!
I think you should consider using the event System.AppDomain.UnhandledException
This event will be raised whenever an exception occurs that is not handled.
As you don't clutter your code with the possibilities of exception, your code will be much better readable. Besides it would give derived classes the opportunity to catch exceptions if they expect ones, without interfering with your automatic exception catcher.
Your design is such, that if someone calls several functions of your derived class and then checks if there are any exceptions the caller wouldn't know which function caused the exception. I assume that your caller is not really interested in which function causes the exception. This is usually the case if you only want to log exception until someone investigates them.
If that is the case consider doing something like the following:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
logger.LogException(ex);
// TODO: decide whether to continue or exit.
}
If you really want to do this only for your abstract base class
public abstract BaseClass
{
private List<Exception> unhandledExceptions = new List<Exception>();
protected BaseClass()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
}
private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
this.UnhandledExceptions.Add(ex);
}
public List<Exception> LastKnownExceptions
{
get { return this.unhandledExceptions; }
}
I had a similar requirement for catching exceptions, but used a specific implementation (i.e. not an abstract class) to encapsulate the handling of errors.
Please note this takes in an argument for any expected exceptions (params Type[] catchableExceptionTypes), but of course you can modify to suit your own requirements.
public class ExceptionHandler
{
// exposes the last caught exception
public Exception CaughtException { get; private set; }
// allows a quick check to see if an exception was caught
// e.g. if (ExceptionHandler.HasCaughtException) {... do something...}
public bool HasCaughtException { get; private set; }
// perform an action and catch any expected exceptions
public void TryAction(Action action, params Type[] catchableExceptionTypes)
{
Reset();
try
{
action();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return;
}
throw;
}
}
// perform a function and catch any expected exceptions
// if an exception is caught, this returns null
public T TryFunction<T>(Func<T> function, params Type[] catchableExceptionTypes) where T : class
{
Reset();
try
{
return function();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return null;
}
throw;
}
}
bool ExceptionIsCatchable(Exception caughtException, params Type[] catchableExceptionTypes)
{
for (var i = 0; i < catchableExceptionTypes.Length; i++)
{
var catchableExceptionType = catchableExceptionTypes[i];
if (!IsAssignableFrom(caughtException, catchableExceptionType)) continue;
CaughtException = caughtException;
HasCaughtException = true;
return true;
}
return false;
}
static bool IsAssignableFrom(Exception exception, Type type)
{
if (exception.GetType() == type) return true;
var baseType = exception.GetType().BaseType;
while (baseType != null)
{
if (baseType == type) return true;
baseType = baseType.BaseType;
}
return false;
}
void Reset()
{
CaughtException = null;
HasCaughtException = false;
}
}

Avoid Try Catch Stements with custom ErrorHandler class - C#

I have a class which exposes some functionality,
and I want to ensure exceptions will be handled by a custom ErrorHandler class.
Currently I can achieve this by a try / catch statement per each method, and process the exception by the error handler there.
My question is if there is a better way / design pattern to do it.
Code:
public class BasicErrorHandler
{
public void ProcessException(Exception ex)
{
//Does error handling stuff
}
}
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
try
{
//Does Something
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
public void MethodB()
{
try
{
//Does Something Else
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
}
In keeping with DRY principles, you could just wrap your try...catch logic into into own method which takes a predicate of the actual work to do:
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
DoWork( () => {
// do something interesting here
});
}
public void MethodB()
{
DoWork( () => {
// do something else interesting here
});
}
private void DoWork(Action action)
{
try
{
action();
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
}
I've crafted this quickly and without thinking too much in the implications, but if you want to avoid all the try/catch blocks, you could do something like:
public class BasicErrorHandler
{
public void ProcessException(Exception ex)
{
//Does error handling stuff
}
public void Do(Action act)
{
try
{
act();
}
catch(Exception ex)
{
ProcessException(ex);
}
}
}
And then use it like:
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
_errorHandler.Do(() => {
//Does Something
});
}
public void MethodB()
{
_errorHandler.Do(() => {
//Does Something Else
});
}
}
Design patterns are there to solve a problem. Which problem are you trying to solve? What is wrong with the Try Catch blocks?
Only thing I can imagine is you want to have more clean code. Some answers suggest a helper method with an action. Given the helper methods that encapsulate a delegate: Do consider the impact on your stack trace and debugging sessions using these delegates. It might make logging etc more hard to understand.
If your intend is to do separation of concern, I would say If you can't handle it, just don't catch the exception. Let the class invoking the method handle it. If you insist to have a handler in your class, I would suggest Inversion of Control. That way, your class is not in control of determining which class should handle its exceptions.
Rx .net is for You. Advanced error handling gives You the ability to highly customize Your error handling. Check out the pages about that.
For example:
var source = new Subject<int>();
var result = source.Catch<int, TimeoutException>(tx=>Observable.Return(-1));
result.Dump("Catch");
source.OnNext(1);
source.OnNext(2);
source.OnError(new ArgumentException("Fail!"));
You'll get the following output:
Catch-->1
Catch-->2
Catch failed-->Fail!
The number of retries, the handling of how much time a method can take, everything can be configured.
The following is an Aspect oriented method of soling the problem, this makes use of PostSharp to do the weaving.
[Serializable]
public class HandleExceptionsAttribute : OnExceptionAspect {
/// <summary>
/// Initializes a new instance of the <see cref="HandleExceptionsAttribute"/> class.
/// </summary>
public HandleExceptionsAttribute() {
AspectPriority = 1;
}
public override void OnException(MethodExecutionArgs args) {
//Suppress the current transaction to ensure exception is not rolled back
using (var s = new TransactionScope(TransactionScopeOption.Suppress)) {
//Log exception
using (var exceptionLogContext = new ExceptionLogContext()) {
exceptionLogContext.Set<ExceptionLogEntry>().Add(new ExceptionLogEntry(args.Exception));
exceptionLogContext.SaveChanges();
}
}
}
}
[HandleExceptions]
public class YourClass {
}

Multiple Implementation Attempts

I am developing a solution which will connect to a wide variety of servers to read data and perform operations. There are many variables which complicate reliable communications such as firewalls, stopped/failed services, authentication differences, and various software configurations. There are methods I can use to work around these issues, though at the time of execution it is not known which will prove successful.
My goal is to create an interface and implementations which can be used to perform operations. The first method call will be to the fastest implementation which works for the majority of devices followed by other calls which can deal with the issues listed earlier.
In a perfect world the process would be written to quickly identify which method would be successful, but in my tests that took as much processing time as simply catching an exception. While performance is always a consideration, in the end it is more important that the task completes successfully.
Below is an example I created which demonstrates a worst case scenario iterating over a list of implementations. While this works well for one method, it doesn't follow the DRY principle when used in 20 or more different operations. One possible solution is Unity and Interception but I found that the invoke method in the call handler uses a resolved implementation, not a list of possible implementations. Unless I am missing something, that doesn't appear to be an option. Also, I will need to follow this pattern for several interfaces, so it would be nice to create a generic handler which can iterate over a list of implementations.
Any advice on how to complete this task would be appreciated!
Interface
public interface IProcess
{
int ProcessItem(string workType);
}
Implementations
public class ProcessImplementation1 : IProcess
{
public int ProcessItem(string workType)
{
throw new TimeoutException("Took too long");
}
}
public class ProcessImplementation2 : IProcess
{
public int ProcessItem(string workType)
{
throw new Exception("Unexpected issue");
}
}
public class ProcessImplementation3 : IProcess
{
public int ProcessItem(string workType)
{
return 123;
}
}
Special Implementation loops through the other implementations until one succeeds without exception
public class ProcessImplementation : IProcess
{
public int ProcessItem(string workType)
{
List<IProcess> Implementations = new List<IProcess>();
Implementations.Add(new ProcessImplementation1());
Implementations.Add(new ProcessImplementation2());
Implementations.Add(new ProcessImplementation3());
int ProcessId = -1;
foreach (IProcess CurrentImplementation in Implementations)
{
Console.WriteLine("Attempt using {0} with workType '{1}'...",
CurrentImplementation.GetType().Name, workType);
try
{
ProcessId = CurrentImplementation.ProcessItem(workType);
break;
}
catch (Exception ex)
{
Console.WriteLine(" Failed: {0} - {1}.",
ex.GetType(), ex.Message);
}
Console.WriteLine();
if (ProcessId > -1)
{
Console.WriteLine(" Success: ProcessId {0}.", ProcessId);
}
else
{
Console.WriteLine("Failed!");
}
return ProcessId;
}
}
}
You could implement the processing operation as a generic extension method that you pass a method that does the processing for a single item:
public static int ProcessItems<T>(this IEnumerable<T> items, Func<T, int> processMethod)
{
foreach (var item in items)
{
try
{
return processMethod(item);
}
catch(Exception) {}
}
return -1;
}
Now you have factored out the actual type of the item and what method you use for processing. The only thing "fixed" is the result type of the generic method which is an integer.
For your current example you could call it like this then:
List<IProcess> implementations = ...;
int processResult = items.ProcessItems(x => x.ProcessItem(workType));
You could use the TryParse pattern in a second interface:
public interface IProcess
{
int ProcessItem(string workType);
}
internal interface ITryProcess
{
bool TryProcessItem(string workType, out int result);
}
public class ProcessImplementation1 : ITryProcess
{
public bool TryProcessItem(string workType, out int result)
{
result = -1;
return false;
}
}
public class ProcessImplementation : IProcess
{
public int ProcessItem(string workType)
{
var implementations = new List<ITryProcess>();
implementations.Add(new ProcessImplementation1());
// ...
int processId = -1;
foreach (ITryProcess implementation in implementations)
{
if (implementation.TryProcessItem(workType, out processId))
{
break;
}
}
if (processId < 0)
{
throw new InvalidOperationException("Unable to process.");
}
return processId;
}
}
Here's a solution similar to the one created by #BrokenGlass if you want something very simple and "generic."
public void TryAllImplementations<TService>(
IEnumerable<TService> services,
Action<TService> operation,
Action<Exception> exceptionHandler = null)
{
int dummy = 0;
TryAllImplementations(
services,
svc => { operation(svc); return dummy; },
exceptionHandler);
}
public TReturn TryAllImplementations<TService, TReturn>(
IEnumerable<TService> services,
Func<TService, TReturn> operation,
Action<Exception> exceptionHandler = null)
{
foreach (var svc in services)
{
try
{
return operation(svc);
}
catch (Exception ex)
{
if (exceptionHandler != null)
exceptionHandler(ex);
}
}
throw new ProgramException("All implementations have failed.");
}
Since I see a Unity tag, you could use ResolveAll<TService>() on your container using your service interface to get all implementations. Combining that with this code, you could do something like an extension method on IUnityContainer:
public static class UnityContainerExtensions
{
public static void TryAllImplementations<TService>(
this IUnityContainer container,
Action<TService> operation,
Action<Exception> exceptionHandler = null)
{
int dummy = 0;
container.TryAllImplementations<TService, int>(
svc => { operation(svc); return dummy; },
exceptionHandler);
}
public static TReturn TryAllImplementations<TService, TReturn>(
this IUnityContainer container,
Func<TService, TReturn> operation,
Action<Exception> exceptionHandler = null)
{
foreach (var svc in container.ResolveAll<TService>())
{
try
{
return operation(svc);
}
catch (Exception ex)
{
if (exceptionHandler != null)
exceptionHandler(ex);
}
}
throw new ProgramException("All implementations have failed.");
}
}
Here's how using it could work:
IUnityContainer container;
// ...
container.RegisterType<IProcess, ProcessImplementation1>();
container.RegisterType<IProcess, ProcessImplementation2>();
container.RegisterType<IProcess, ProcessImplementation3>();
// ...
container.TryAllImplementations(
(IProcess svc) => svc.ProcessItem(workType),
ex => Console.WriteLine(
" Failed: {0} - {1}.",
ex.GetType(),
ex.Message));

Categories

Resources