I have the below mapper json file, which tells me for a given exception, which error handling policy I want to use.
{
"ExceptionMappers": [
{
"ExceptionName": "TimeoutException",
"ExceptionType": "Transient",
"Policy": "WaitAndRetry",
"WaitType": "Linear"
},
{
"ExceptionName": "DivideByZeroException",
"ExceptionType": "Permanent",
"Policy": "CircuitBreaker"
},
{
"ExceptionName": "StackOverflowException",
"ExceptionType": "LogOnly",
"Policy": "WaitAndRetry",
"WaitType": "Linear"
}
]
}
Then using the below code I am trying to get the type of exception and apply a policy using which the action can be called. But here I am stuck, how to get the exception type from a string name.
public void Execute(Action action, string exceptionName)
{
var filePath = @"appsetting.json";
var exceptionMapperJson = System.IO.File.ReadAllText(filePath);
var rootNode = JsonConvert.DeserializeObject<RootObject>(exceptionMapperJson);
var exceptionNode = rootNode.ExceptionMappers.FirstOrDefault(e => e.ExceptionName.Equals(exceptionName));
var exceptionObject = Type.GetType(exceptionName);
if (exceptionNode != null)
{
// Here I need the exception from the string value
Policy.Handle<TimeoutException>().Retry().Execute(action);
}
else
{
// No Policy applied
Policy.NoOp().Execute(action);
}
}
Per @thehennyy 's comment, Jon Skeet's answer to a similar question covers how to use reflection to invoke a generic method when the generic type is known only at runtime. The slight difference from the linked answer: because .Handle<TException>()
is a static method on Policy
, pass null
as the first argument to MethodInfo.Invoke()
.
Alternatively, because Polly offers Handle clauses which can take a predicate, you could simply:
var exceptionType = Type.GetType(exceptionName);
if (exceptionNode != null)
{
Policy.Handle<Exception>(e => exceptionType.IsAssignableFrom(e.GetType())) // etc
}
This live dotnetfiddle example demonstrates it working.
Or, make your wrapper method itself generic:
public void Execute<TException>(Action action) where TExecption : Exception
{
// reverses the approach:
// you'll want a typeof(TException).Name, to get the string name of the exception from TException
// Then you can just Policy.Handle<TException>(...) when you construct the policy
}
As another refinement, you could consider constructing the policies only once at startup, and placing them in PolicyRegistry