SignalR step-by-step (2) Generic Hub

Source: Internet
Author: User

In the last article, two questions are thrown at the end of the article:

If you want the client method to appear on the server with a strong type, and the server method also appears on the client with a strong type, you must declare a carrier similar to the contract. For example:

public interface IChatClient    {        void broadcast(string name, string message);    }
public interface IChatHub    {        void Send(string name, string message);    }

Create the ChatClient interface and the ChatHub interface respectively.

public class ChatHub : Hub<IChatClient>{...}

This is the final goal, a generic Hub.

Well, now we need to analyze how to make the Hub support generics.

First, let's take a look at how the Hub operates the client:

Clients.AllExcept(Context.ConnectionId).broadcast(name, message);

The Hub uses Clients to perform operations on all Clients. So what type of Clients is this?

// Summary: // Gets a dynamic object that represents all clients connected to this hub (not // hub instance). IHubCallerConnectionContext Clients {get; set ;}

The IHub interface shows that the Clients type is IHubCallerConnectionContext. Click here to see:

// Summary: // Encapsulates all information about an individual SignalR connection for an // Microsoft. aspNet. signalR. hubs. IHub. public interface IHubCallerConnectionContext: IHubConnectionContext {[Dynamic] dynamic Caller {get;} [Dynamic] dynamic Others {get;} dynamic OthersInGroup (string groupName ); dynamic OthersInGroups (IList <string> groupNames );}

IHubCallerConnectionContext inherits IHubConnectionContext, and click it to view it:

// Summary: // Encapsulates all information about a SignalR connection for an Microsoft. aspNet. signalR. hubs. IHub. public interface IHubConnectionContext {[Dynamic] dynamic All {get;} dynamic AllExcept (params string [] excludeConnectionIds); dynamic Client (string connectionId); dynamic Clients (IList <string> connectionIds ); dynamic Group (string groupName, params string [] excludeConnectionIds); dynamic Groups (IList <string> groupNames, params string [] excludeConnectionIds); dynamic User (string userId );}

At a glance, the operation methods of all Clients are here, all of which are dynamic, which is why they are written to Clients in the Hub. all. when xxx is running, what types of operations are there? Try:

Public class ClientProxy: DynamicObject, IClientProxy {public ClientProxy (IConnection connection, IHubPipelineInvoker invoker, string hubName, IList <string> exclude); public Task Invoke (string method, params object [] args); public override bool TryInvokeMember (InvokeMemberBinder binder, object [] args, out object result );}

// Summary: // A server side proxy for the client side hub. public interface IClientProxy {// Summary: // Invokes a method on the connection (s) represented by the Microsoft. aspNet. signalR. hubs. IClientProxy // instance. //// parameter: // method: // name of the method to invoke // args: // argumetns to pass to the client /// the returned result is: // A task that represents when the data has been sent to the client. task Invoke (string method, params object [] args );}}

As you can see, if IClientProxy is used for injection during the runtime, it is an Invoke method.

Okay. You can have some ideas here.

The core attack points have been found. After 4 is solved, 1 can be solved all the way. How can I enable the IClientProxy Invoke to be automatically called by all methods of T? AOP is acceptable! You can use Castle to dynamically weave T. Now you can create a Hub extension class:

public static class HubExtensions    {        static readonly ProxyGenerator generator = new ProxyGenerator();        public static T GetClientBehavior<T>(this IClientProxy clientProxy) where T : class        {            return (T)generator.CreateInterfaceProxyWithoutTarget<T>(new ClientBehaviorInterceptor(clientProxy));        }    }

Let all iclientproxies execute the GetClientBehavior method, load the interceptor internally, and insert IClientProxy into the interceptor.

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);        }    }

In the interceptor, whenever T executes the method, clientProxy executes the Invoke method and passes in the T method name and T parameter, this achieves the effect of dynamically calling the client method to pass in parameters and execute them.

Then, write a Hub <T>.

public abstract class Hub<T> : Hub where T : class    {        protected T All { get { return (Clients.All as IClientProxy).GetClientBehavior<T>(); } }        protected T Any(params string[] connectionIds)        {            return (Clients.Clients(connectionIds) as IClientProxy).GetClientBehavior<T>();        }        protected T Except(params string[] connectionIds)        {            return (Clients.AllExcept(connectionIds) as IClientProxy).GetClientBehavior<T>();        }        protected T Client(string connectionId)        {            return (Clients.Client(connectionId) as IClientProxy).GetClientBehavior<T>();        }        protected T Caller { get { return (Clients.Caller as IClientProxy).GetClientBehavior<T>(); } }    }

Write all the operations in Clients here, and write five operations in the example. Through the expansion method just now, the returned T has already passed through AOP. Finally, modify the original ChatHub:

Let ChatHub inherit Hub <T> and T be IChatClient. It indicates that the client method can be called with a strong type using the handle T method. Run the following command:

At this point, the transformation of the server end is complete. The server can accept strong client behaviors.

In the next article, we will perform a forced type transformation on the client.

 

Finally attached a chat room based on SignalR toy, green non-toxic: http://www.royarea.cn/chatroom

 

Reprinted please indicate the source:Http://www.cnblogs.com/royding/p/3750412.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.