SignalR循序渐进(二)泛型Hub(二)
,就需要有一个Hub的类,然后把Clients里所有的操作在Hub中重新实现一次。
然后T又是客户端的行为接口,因此,需要对Hub进行静态扩展,让IClientProxy的Invoke方法能够被T的所有方法自动调用。
核心攻克点找到了,解决了4,就能一路解决1。怎样才能让IClientProxy的Invoke自动的被T的所有方法调用呢?AOP可以!可以用Castle对T进行动态织入。到这儿可以动手了,先建立一个Hub扩展类:
复制代码
public static class HubExtensions
{
static readonly ProxyGenerator generator = new ProxyGenerator();
public static T GetClientBehavior(this IClientProxy clientProxy) where T : class
{
return (T)generator.CreateInterfaceProxyWithoutTarget(new ClientBehaviorInterceptor(clientProxy));
}
}
复制代码
让所有的IClientProxy执行GetClientBehavior方法,然后内部进行拦截器装载,并将IClientProxy塞进拦截器。
复制代码
public class ClientBehaviorInterceptor:IInterceptor
{
public ClientBehaviorInterceptor(IClientProxy clientProxy)
{
this.clientProxy = clientProxy;
}
IClientProxy clientProxy;
public void Intercept(IInvocation invocation)
clientProxy.Invoke(invocation.Method.Name, invocation.Arguments);
}
}
复制代码
拦截器中,每当T执行方法的时候,clientProxy就执行Invoke方法,把T的方法名和T的参数传入,这就达到了原先动态调用客户端方法传入参数并执行的效果。
然后就是写一个Hub了。
复制代码
public abstract class Hub : Hub where T : class
{
protected T All { get { return (Clients.All as IClientProxy).GetClientBehavior(); } }
protected T Any(params string[] connectionIds)
{
return (Clients.Clients(connectionIds) as IClientProxy).GetClientBehavior();
}
protected T Except(params string[] connectionIds)
{
return (Clients.AllExcept(connectionIds) as IClientProxy).GetClientBehavior();
}
protected T Client(string connectionId)
{
return (Clients.Client(connectionId) as IClientProxy).GetClientBehavior();
}
protected T Caller { get { return (Clients.Caller as IClientProxy).GetClientBehavior(); } }
}