WitCom: Dynamic Proxy vs Static Proxy

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<IExampleService>();

				
			

You can use the static proxy:

				
					var service = client.GetService<IExampleService>(interceptor => new ServiceProxy(interceptor));

				
			

Beyond this change, the rest of the workflow with WitCom remains unchanged.

Advantages of Static Proxy

  1. Compatibility with AoT: The static proxy works seamlessly in Ahead-of-Time (AoT) compilation environments, such as Blazor, where runtime code generation is unsupported.

  2. Improved Startup Performance: Since the proxy code is generated at compile time, runtime reflection overhead is eliminated, resulting in faster application startup.

  3. No Dependency on Reflection.Emit: Unlike DynamicProxy, the static proxy does not rely on Reflection.Emit, making it suitable for platforms that restrict dynamic IL generation.

Disadvantages of Static Proxy

  1. 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.

  2. 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:

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.

Leave a Reply

Your email address will not be published. Required fields are marked *