By default, Castle DynamicProxy serves as the primary tool in WitCom for creating proxy objects based on interface contracts. This allows developers to seamlessly interact with remote services as if they were local objects. The DynamicProxy supports intercepting function calls, property access, and event subscriptions, making it an incredibly versatile solution for .NET development. Moreover, it effortlessly handles generic methods, where parameter types are undefined at the interface declaration stage.
However, DynamicProxy is not universally applicable. For instance, it does not work in Ahead-of-Time (AoT) compilation environments, such as Blazor, where runtime code generation is unsupported.
For such scenarios, WitCom introduces a static proxy implementation based on Source Generation (Roslyn API).
How to Use Static Proxy
To utilize the static proxy in WitCom, follow these steps:
1. Add the OutWit.Common.Proxy Package to Your Contract Project
Install the OutWit.Common.Proxy
package, which provides the necessary base classes and attributes for static proxy generation:
dotnet add package OutWit.Common.Proxy
2. Mark Your Interface with the ProxyTarget Attribute
Apply the ProxyTarget
attribute to the interface representing your contract:
using OutWit.Common.Proxy;
[ProxyTarget]
public interface IExampleService
{
event ExampleServiceEventHandler ProcessingStarted;
event ExampleServiceProgressEventHandler ProgressChanged;
event ExampleServiceProcessingEventHandler ProcessingCompleted;
bool StartProcessing();
void StopProcessing();
}
By default, this will generate a proxy class named IExampleServiceProxy
.
To specify a custom name for the generated proxy class, pass the desired name as a parameter to the attribute:
[ProxyTarget("ServiceProxy")]
public interface IExampleService
{
event ExampleServiceEventHandler ProcessingStarted;
event ExampleServiceProgressEventHandler ProgressChanged;
event ExampleServiceProcessingEventHandler ProcessingCompleted;
bool StartProcessing();
void StopProcessing();
}
In this case, a proxy class named ServiceProxy
will be generated.
Note: Generic methods are not supported in static proxy generation. Attempting to include generic methods in your interface will result in a compilation error.
3. Add the OutWit.Common.Proxy.Generator Package to Your Client Project
To enable proxy generation, add the OutWit.Common.Proxy.Generator
package to the client project:
dotnet add package OutWit.Common.Proxy.Generator
Build the project, and the proxy class will be generated automatically.
Using the Static Proxy with WitCom
Once the client is initialized:
var client = WitComClientBuilder.Build(options =>
{
options.WithWebSocket("ws://localhost:5000");
options.WithJson();
options.WithEncryption();
});
await client.ConnectAsync(TimeSpan.FromSeconds(5), CancellationToken.None);
Instead of creating a dynamic proxy:
var service = client.GetService();
You can use the static proxy:
var service = client.GetService(interceptor => new ServiceProxy(interceptor));
Beyond this change, the rest of the workflow with WitCom remains unchanged.
Advantages of Static Proxy
Compatibility with AoT: The static proxy works seamlessly in Ahead-of-Time (AoT) compilation environments, such as Blazor, where runtime code generation is unsupported.
Improved Startup Performance: Since the proxy code is generated at compile time, runtime reflection overhead is eliminated, resulting in faster application startup.
No Dependency on
Reflection.Emit
: Unlike DynamicProxy, the static proxy does not rely onReflection.Emit
, making it suitable for platforms that restrict dynamic IL generation.
Disadvantages of Static Proxy
Less Flexible: Static proxies require explicit setup at compile time, which makes them less adaptable for scenarios where runtime behavior needs to be dynamically adjusted.
Increased Build Complexity: Using source generators introduces additional build steps and dependencies, which may complicate the development process.
References and Resources
To explore more about WitCom and its static proxy implementation, refer to the following resources:
- OutWit.Common.Proxy.Generator: GitHub Repository
- OutWit.Common.Proxy: GitHub Repository
- Static Proxy Example: GitHub Example
- WitCom Overview: Detailed Article
- WitCom Project Root: GitHub Repository
Conclusion
The choice between DynamicProxy and Static Proxy ultimately depends on your application’s requirements. If you’re working in AoT environments or need a solution without dynamic IL generation, static proxies provide a powerful alternative. However, for maximum flexibility and ease of use in runtime environments, DynamicProxy remains an excellent choice.