Interface Proxy
Tags: csharp, dotnet
Published: 2023-10-11 21:25:41

## Terminology
<u>NET</u>: net core 6.0+
<u>NETFRAMEWORK</u>: classic or legacy .NetFramework

## History 📚

A technology called Remoting was once in fashion. This technology was built as an alternative to <u>DCOM</u>.

It was available for <u>NETFRAMEWORK</u>.

It provided classes and interfaces that allowed developers to create and configure distributed applications.

These classes and interfaces lived in the namespace  [System.Runtime.Remoting](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.remoting?view=netframework-4.8.1)

The developer requested an instance of a remote service and the remoting infrastructure returned a proxy (a Transparent Proxy).

Depending on the activation mode, each call to this proxy service was handled in the server by a new instance or by the same instance. This was also related to the life cycle of the instances on the remoting server.

This can be seen summarized in the <u>WellKnownObjectMode </u>enumeration.

```csharp
public enum WellKnownObjectMode
{
    //Every call is serviced by the same instance
    Singleton = 1,
    //Every call is serviced by a new instance.
    SingleCall
}
```
# Problems 😰

With the arrival of <u>NET</u>, Microsoft abandoned this technology.

How could we migrate this technology to <u>NET</u> in a Windows Forms Application with a SingleCall Remoting implementation?

Microsoft offered several alternatives, for example <u>streamjsonrpc</u>

{% embed https://github.com/microsoft/vs-streamjsonrpc %}

Or <u>gRpc</u>

{% embed https://github.com/grpc/grpc-dotnet %}

# Alternate Solution 🎃

Personally I find it easier to forward http calls to a <u>REST API</u> if you had a stateless server.

You have more control and i think it is more standard.

Now imagine that you have 1000+ interfaces with their respective methods.

How can you redirect those calls to our new REST server?

Let's take an example to better understand the problem. Below we can see a payment service with a method:

```csharp
public interface IPayment
{
    Task<Payment> Checkout(Basket basket);
}
```

One assumption here (and most of the methods) is that Basket and Payment classes inherits from [System.Data.Dataset](https://learn.microsoft.com/es-es/dotnet/api/system.data.dataset?view=netframework-4.8) 😨

One possibility is to use the Service Locator pattern and Inversion of Control.

Since we have these interfaces, we can decorate them with some attribute that indicates that they participate in IOC.

Then we can call an instance calling something like:

```csharp
IPayment payment = ServiceLocator.Current.GetInstance<IPayment>();
payment.Checkout(...)
```

But what happens if you are not allowed to use an IOC? (insert multiple and diverse causes here) 😭

Not everything is lost.

We can create a class that is a <u>RealProxy</u> that makes the appropriate calls to the remote server and returns a <u>TransparentProxy</u>, which as if it were a black box allows us to invoke the methods of our interface and our new server will respond.

Suppose that in our legacy application we have a static class called <u>RemotingServiceFactory</u> that returns instances of <u>IPayment</u> and other services.

One example of use would be as follows:

```csharp
// This is a Transparent Proxy returned by 
// the RemotingServiceFactory class
IPayment proxy = RemotingServiceFactory.GetService<IPayment>();

Basket basket = new ();
basket.AddProduct(new Product { Name = "Bananas", Quantity = 10 });

// This is the actual call to remote service
Payment response = await proxy.Checkout(basket);
```

We can modify <u>RemotingServiceFactory.GetService</u> to forward 
 calls from some services to our new server and be able to incrementally migrate our services.

We store the types of those services that we have migrated in a dictionary called <u>_httpServices</u> so that if when requesting a service, its type is among them, we return our new TransparentProxy.

```csharp
public static T GetService<T>() where T : class
{
    if (_httpServices.TryGetValue(typeof(T), out IInterceptor? interceptor))
    {
        // New
        return GetHttpService<T>(interceptor);
    }
    else
    {
        // Legacy
        return GetRemotingService<T>();
    }
}
```

Wait a minute, what is that interface called <u>IInterceptor</u>?

It's a class that intercepts the calls to our <u>IPayment</u> and other services and make the real call without the need to implement that interface 😎

```csharp
public class SingleDataSetInterceptor : IInterceptor
{
    ...
    ...

    // This method is called every time we call a method in our interface
    public void Intercept(IInvocation invocation)
    {
        invocation.ReturnValue = InvokeHttpPostAsync(invocation.Method.DeclaringType?.FullName, invocation.Method.Name
            , (DataSet)invocation.GetArgumentValue(0), invocation.Method.ReturnType);
    }

    private async Task<DataSet> InvokeHttpPostAsync(string? classPath, string methodName, DataSet? parameter, Type returnType)
    {
        ArgumentNullException.ThrowIfNull(classPath);
        ArgumentNullException.ThrowIfNull(methodName);
        ArgumentNullException.ThrowIfNull(parameter);

        using HttpResponseMessage response = await _httpClient.PostAsync($"/{classPath}/{methodName}"
            , new ObjectContent(parameter.GetType(), parameter, _httpSendFormatter));
        response.EnsureSuccessStatusCode();

        return (DataSet)await response.Content.ReadAsAsync(returnType, _httpReceiveFormatters);
    }
}

```

Now, we need some magic to glue all the parts, and that glue is the fantastic library <u>Castle.Core</u>

<u>Castle.Core</u> includes a lightweight runtime proxy generator that we can use to create TransparentProxies of our interfaces without being implemented.

{% embed https://github.com/castleproject/Core %}

```csharp
ProxyGenerator generator = new ProxyGenerator();
var interceptor = new SingleDataSetInterceptor(...);
// This is magic !!
IPayment proxy = generator.CreateInterfaceProxyWithoutTarget<IPayment>(interceptor);

Payment response = await proxy.Checkout(...);
```

If we include this in the private method GetHttpService<T> of the static class <u>RemotingServiceFactory</u> then we have completed our journey:

```csharp
    //_generator is a ProxyGenerator
    private static T GetHttpService<T>(IInterceptor interceptor) where T :  class
    {
        return _generator.CreateInterfaceProxyWithoutTarget<T>(interceptor);
    }
```

As allways all the code is hosted in Github.

Be kind and love your family 💖

{% embed https://github.com/NetDefender/InterfaceProxy %}