Question

I am trying to use Castle DynamicProxy to implement a typesafe version of a SignalR Hub. The goal being when I use Clients.All rather than getting a dynamic object back I have an interface to use.

The code is rather hacky at the moment but I wanted to prove that it will work before I go through the trouble of making it nice:

public interface IChatClient
{
    void broadcastMessage(string name, string message);
}

public class ChatHub : TypeSafeHub<IChatClient>
{
    public void Send(string name, string message)
    {
        Clients.All.broadcastMessage(name, message);
    }
}

public abstract class TypeSafeHub<TInterface> : Hub where TInterface:class
{
    public new TypeSafeHubCallerConnectionContext<TInterface> Clients
    {
        get
        {
            return new TypeSafeHubCallerConnectionContext<TInterface>(base.Clients);
        }
    }
}

public class TypeSafeHubCallerConnectionContext<T> where T:class
{
    private IHubCallerConnectionContext context;
    private ProxyGenerator proxyGen;

    public TypeSafeHubCallerConnectionContext(IHubCallerConnectionContext context)
    {
        this.context = context;
        proxyGen= new ProxyGenerator();
    }

    public T All
    {
        get
        {
            return proxyGen.CreateInterfaceProxyWithTarget<T>(context.All);
        }

Right now when I'm returning the proxy it fails because the target does not implement the interface.

Is there an easy way to achieve this goal or should I look at using an InterfaceProxyWithoutTarget and using an interceptor to wire up the call to the dynamic.

Was it helpful?

Solution

You seem to be on the right track.

This is a feature slated for release in SignalR 2.1. You can look at how it is implemented here: https://github.com/SignalR/SignalR/commit/3c4b8794b0f512daec677110a8e41ac717514584

While there is likely a way to do this with Castle DynamicProxy, it might be simpler to use ImpromptuInterface.

Every call made to TypedClientBuilder<T>.Build(_dynamicContext...) could be replaced with Impromptu.ActLike<T>(_dynamicContext...). In your case, the call to Impromptu.ActLike would replace proxyGen.CreateInterfaceProxyWithTarget.

If you feel really adventurous, you can try out the SignalR nightlies from MyGet which already have the feature included.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top