Recently, I am curious about what WCF client really does when creating proxy object (ClientBase
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
It is just a snapshot; actually, there are many other members and methods. I only show you two important members: ChannelFactoryRef
Indeed, there is a cache called factoryRefCache of type ChannelFactoryRefCache
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
What is the job of the ChannelFactory
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
Now, we need to use ChannelFactory
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.