What WCF client does ... (1)

Recently, I am curious about what WCF client really does when creating proxy object (ClientBase) or use the ChannelFactory directly.
If service reference is added by using the Visual Studio directly, it will automatically create a service client for you, it implements the service contract and inherits from the ClientBase; the generic type TChannel, it is not the IChannel, it is the service contract class. The following diagram is the class diagram for ClientBase.

It is just a snapshot; actually, there are many other members and methods. I only show you two important members: ChannelFactoryRef and EndpointTrait. When you create the client object, in the ClientBase class, the constructor will create one EndpointTrait object, it is used to create ChannelFactory. After that, the ClientBase is going to initialize the ChannelFactoryRef object.
Indeed, there is a cache called factoryRefCache of type ChannelFactoryRefCache, it is initialized in the static constructor of the ClientBase. When it initializes the ChannelFactoryRef object, it tries to get the object from the cache first, but if the state of the object isn’t opened, that means the object cannot be used, it will remove it from the cache and create a new object; else it uses it and adds one more reference. So, multiple clients for the same service may use the same ChannelFactory.
Let’s see what is going to happen when it needs to create a new object. It uses the EndpointTrait object to create the ChannelFactory object, and passes it to the ChannelFactoryRef constructor. You may have some imagination already; the ChannelFactoryRef is just a reference counter class for the ChannelFactory. After that, the ClientBase delegates all the work to the inner ChannelFactory object.
What is the job of the ChannelFactory? It creates the service endpoint first; then, it needs to configure this service endpoint. I use a diagram to show you the process.

From the diagram, it searches the configuration file first, if there is such a file, it read the configuration from it (LoadChannelBehaviors); if not, it uses some common configuration (LoadCommonClientBehaviors). In the LoadBehaviors() method, it gets all the IEndpointBehavior objects. Behavior is the most useful extensible point in WCF, IEndpointBehavior allows you to achieve the extensibility in client. If you want to apply you behavior to the client, you need to add your IEndpointBehavior to the IEndpointBehavior collection of ServiceEndpoint before it calls the ChannelFactory.Open() method.Now, we need to use ChannelFactory.CreateChannel(), here is what happens.

It ensures the communication state is opened first. If the state isn’t opened, it calls Open(), in this step, it initializes the channel and applies some configuration (call opening()), let’s see what happens in detail.

ComputeContractRequirements() method is used to inject into the ContractDescription, it collects some information from it, such as the session mode, whether the operation is one-way etc. . In the BuildProxyBehavior() method, it gets the service endpoint’s contract description; then, based on the operation descriptions of the contract, it determines which operation type should be built. If the operation is initiated by the server, then it builds the dispatch operation (BuildDispatchOperation), because it acts as a receiver; otherwise, it builds a proxy operation (BuildProxyOperation), because it acts as a sender. In both methods, it adds the operation into the one collection of the ClientRuntime. The next step is to apply the client behavior, which is why I say you should add your IEndpointBehavior to the collection before you open it. In the BuildOperations() method, the IOperationBehavior will be applied according to their operation type: ApplyClientBehavior or ApplyDispatchBehavior. The ComputeRequiredChannels() uses the results from the ComputeContractRequirements() to determine which channel type it needs. Then, it compares these requirements with the Binding. If something mismatch, it throws exception. That’s all what happens before it opens the channel.
In order to get the service client, it creates a ServiceChannel object, CreateProxy() method creates the service client, the ServiceChannelProxy inherits the RealProxy, which is in the Remoting. The client uses the client to communicate with the service. WCF client runtime will actually intercept every WCF service call by injecting a TransparentProxy and ServiceChannelProxy between WCF service call site and underlying the channel stack. The reason WCF implements the client runtime the way it is that WCF needs to differ between normal method invocation and WCF service invocation on service proxy objects.
OK, the channel is prepared; we are ready to invoke the service, we can call the service just as invoking local method through the client. It is something like RPC or RMI, but there are many differences, I will explain what happens in this process in future.
posted @ 2011-03-02 15:34  yedafeng  阅读(398)  评论(0编辑  收藏  举报