Configure Polly policies via a proxy.
A combination of Polly and Castle Dynamic Proxy as an alternative way to configure Polly policies to any virtual method being called without modifying the existing code.
To install the package run the following command on the Package Manager Console:
PM> Install-Package Polly.Proxy
Create a new proxy for a class (or interface) by using PollyProxy<T>.Create()
helper method:
var proxy = PollyProxy<ISvcClient>.Create(new SvcClient(), policies => policies
.For(_ => _.GetSomeData(), Policy.Handle<Exception>().Retry(3))
.Default(Policy.NoOp()));
Given an existing interface/class pair:
public interface ISvcClient
{
Data[] GetSomeData();
}
public class SvcClient : ISvcClient
{
public Data[] GetSomeData()
{
// ...
}
}
That is used in some other place:
public class AnotherClass
{
private ISvcClient _svcClient = new SvcClient();
public void Run()
{
var data = _svcClient.GetSomeData();
Process(data);
// ...
}
}
You can set Polly policies to the method calls for your instance of YourClass
by
creating a new proxy instead:
using Polly;
public class AnotherClass
{
private ISvcClient _svcClient; // <-- Will proxy this instance
public AnotherClass()
{
_svcClient = PollyProxy<ISvcClient>.Create(new SvcClient(), p => p
.Default(Policy.Handle<Exception>().Retry(2)));
}
public void Run()
{
var data = _svcClient.GetSomeData(); // <-- This call will be handled by Polly
// ...
}
}
You can use the fluent API to map the policies rules:
.For(string methodName, Policy policy)
: Maps a policy for a method by its case-sentitive name..For(Expression methodExpression, Policy policy)
: Maps a policy for a method by an expression..When(Func<MethodInfo, bool> selector, Policy policy)
: Specifies a policy to be used under certain condition on theMethodInfo
being called..Map(Func<MethodInfo, Policy> policyBuilder)
: A function of theMethodInfo
being called that returns the policy to use (or NULL)..Default(Policy policy)
: Defines a default Policy to use for any other method not mapped by other rules.
Notes:
- The order in which the fluent API methods are called, defines the precedence for the rules evaluation, except for the
.Default(Policy)
which can be called in any order.- You can set/return a NULL policy for a rule to indicate the rule is not matching any policy.
The PollyProxy<T>.Create()
method returns a proxy object that inherits from the proxied class / implements proxied interface T and forwards calls to the real object.
Give special attention to the generic type argument T
, it can be:
- An interface: Will generate an interface proxy to log all the interface member calls. (Recommended)
- A class type: Will generate a class proxy to log virtual member calls.
- When using an interface proxy, the interception is limited to the members of the interface.
- When using a class proxy, the interception is limited to its virtual members: non-virtual methods can't be automatically proxied.