Castle Dynamic Proxy: github
Castle Dynamic Proxy is a powerful library for generating dynamic proxy objects at runtime in .NET. It is widely used in mocking frameworks like Moq to simulate and intercept the behavior of objects during testing.
In mocking scenarios, Dynamic Proxy allows developers to create fake implementations of interfaces or virtual methods. These proxy objects can:
Intercept method calls
Return predefined values
Track how methods are used
Verify interactions
By enabling such features, Castle Dynamic Proxy plays a key role in unit testing, dependency isolation and aspect-oriented programming(AOP) in the .NET ecosystem.
What's a proxy?
A proxy, in its most general form, is a class functioning as an interface to another thing. The other thing could be anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.
What is an interception pipeline?
The interception pipeline is a mechanism that allows you to intercept, inspect, and optionally modify the behavior of method calls before and after they are executed.
A simple example for Dynamic Proxy:
Note: If you implement an interceptor and handle the method, the method is handled. If you don't handle it, nothing happens and it may return null.
public interface ICalculator
{
int Add(int a, int b);
int Multiply(int a, int b);
}
public class Calculator: ICalculator
{
public int Add(int a, int b) => a + b;
public int Multiply(int a, int b) => a * b;
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine($"[Before]Intercepted in {invocation.Method.Name}");
// If I filter a method by its Name, and other methods which not call invocation.Proceed will not be handled.
invocation.Proceed();
Console.WriteLine($"[After]Intercepted in {invocation.Method.Name}, return {invocation.ReturnValue}");
}
}
// Program.cs
var proxyGenerator = new ProxyGenerator();
var calculator = new Calculator();
var interceptor = new LoggingInterceptor();
ICalculator proxy = proxyGenerator.CreateInterfaceProxyWithTarget<ICalculator>(calculator, interceptor);
int sum = proxy.Add(3, 4);
int product = proxy.Multiply(3, 4);
What's limitations of using dynamic proxy
1.Only interfaces or virtual methods
Castle Dynamic proxy can only proxy: Interfaces, Classes with virtual methods(non-virtual methods, static methods, constructors, and private methods in the classes cannot be intercepted.)
2.Sealed classes or methods cannot be proxied
Overall, Moq's abilities are based on Castle Dynamic proxy. It can only mock what Castle can proxy.
What Moq does internally
- Uses Castle's ProxyGenerator: Moq creates a dynamic proxy that implements your interface at runtime. No need for a real implementation - the proxy just fake it.
- Intercepts method calls: When you call mock. Object.SomeMethod(), Castle intercepts the call and sends it through Moq's internal interceptors.
- Moq handles the logic: Moq stores setups like .Setup(x => x.DoStuff()). At runtime, when the proxy is called, Moq matches it against your setups. If there's a match, it returns the value or behavior your configured. If not, it may return default or throw, depending on how strict the mock is.
Top comments (0)