ChannelAdam WCF Library — Version 2 Documentation
Basic Usage
Create a ServiceConsumer with the ServiceConsumerFactory
The first thing you need to understand is that you consume your service operations through the usage of the ChannelAdam.ServiceModel.ServiceConsumer
class.
The second thing you need to understand is that the best way to create the ServiceConsumer
is by using the Create
method on the ChannelAdam.ServiceModel.ServiceConsumerFactory
.
In order to use the ServiceConsumerFactory.Create
method, simply pass in as a parameter a factory method for creating the service client.
For example:
1IServiceConsumer<IFakeService> service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient()));
The ServiceConsumerFactory.Create
method returns a IServiceConsumer<TServiceInterface>
type.
In all further examples, I will use the var
keyword instead - such as:
1var service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient()));
Alternatively, you can pass in as a string parameter the endpoint configuration name from the service client section of your application’s .config file. For example:
1var service = ServiceConsumerFactory.Create<IFakeService>("BasicHttpBinding_IFakeService"));
Four Ways to Clean Up the ServiceConsumer
There are four ways in which the ServiceConsumer
can be cleaned up:
- Implicitly via the Using statement;
- Explicitly with the Close method;
- Explicitly with the Dispose method; or
- Automatically by the Garbage Collector.
1. The Using Statement
The recommended and easiest way to use the ServiceConsumer is with the using
statement - because it is a well behaved implementation of IDisposable
(unlike Microsoft’s service clients!).
The service channel will automatically be correctly disposed and closed or aborted, no matter what happens.
1using (var service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient())))
2{
3 ...
4}
2. The Close Method
The ServiceConsumer
and underlying channel can be closed immediately by calling the Close
method on the ServiceConsumer
instance.
1service.Close();
If you want to, you still can immediately call another service operation via that same ServiceConsumer
instance, as under the covers, a new service channel will be created seamlessly and automatically.
3. The Dispose Method
The ServiceConsumer
and underlying channel can be disposed of immediately by calling the Dispose
method on the ServiceConsumer
instance.
1service.Dispose();
As per standard IDisposable
concepts, you should not attempt to reuse the ServiceConsumer
after disposing it.
4. Garbage Collection
If you happen to accidently forget to wrap your ServiceConsumer
instance in a Using
statement or call the Close
method, rest assured that the ServiceConsumer
will still be cleaned up! When the ServiceConsumer
instance goes out of scope, the .NET Garbage Collector will [eventually] kick in and call its destructor/finalise method, thus correctly cleaning up the service channel and preventing any leaks.
Since there is an indeterminate amount of time before the Garbage Collector kicks in, I would recommend the Using
statement approach, as it minimises the number of open channels and other resources currently in use, over the lifetime of your application.
How To Call a Service Operation
There are two ways in which to call a service operation via the ServiceConsumer
:
- Via the
Operations
property; or - Via the
Consume
method.
The Operations Property
The Operations
property exposes the interface of your service. It can be used just like the normal service client that you already would be familiar with.
Below is an example of how to call the AddIntegers
operation via the Operations
property.
1using (var service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient())))
2{
3 try
4 {
5 int actualValue = service.Operations.AddIntegers(1, 1);
6 ...
7 }
8 ...
9}
And below is an example of how to do some exception handling with it.
1using (var service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient())))
2{
3 try
4 {
5 int actualValue = service.Operations.AddIntegers(1, 1);
6 ...
7 }
8 catch (FaultException<MyCustomException> fe)
9 {
10 Console.WriteLine("Service operation threw a custom fault: " + fe.ToString());
11 }
12 catch (FaultException fe)
13 {
14 Console.WriteLine("Service operation threw a fault: " + fe.ToString());
15 }
16 catch (Exception ex)
17 {
18 Console.WriteLine("An unexpected error occurred while calling the service operation: " + ex.ToString());
19 }
20}
There is no need to catch a CommunicationException
or TimeOutException
and try to perform the Close/Abort pattern, as the underlying channel is dealt with automatically for you by the ServiceConsumer
.
The Consume Method
As an alternative to the Operations
property, you can call a service operation via the Consume
method on the ServiceConsumer
instance.
The Consume
method returns an instance of IOperationResult<TReturnTypeOfYourOperation>
which wraps the result of the operation. This interface has the following helpful properties:
TReturnTypeOfYourOperation Value
- which gives you access to the return value from the operation;bool HasException
- whether there was an exception thrown by the service operation;bool HasNoException
- whether there was not an exception thrown by the service operation;bool HasFaultException
- whether an exception of typeFaultException
was thrown by the service operation;bool HasFaultException<OfThisType>
- whether an exception ofFaultException<OfThisType>
was thrown by the service operation; andException Exception
- the exception that was thrown by the service operation.
Below is an example of how to call the AddIntegers
operation via the Consume
method.
1using (var service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient())))
2{
3 IOperationResult<int> result = service.Consume(operation => operation.AddIntegers(1, 1));
4
5 if (result.HasNoException)
6 {
7 Console.WriteLine("Result was: " + result.Value);
8 ...
9 }
10 ...
11}
And below is an example of how to do some exception handling with IOperationResult
.
1using (var service = ServiceConsumerFactory.Create<IFakeService>(() => new FakeServiceClient())))
2{
3 var result = service.Consume(operation => operation.AddIntegers(1, 1));
4
5 if (result.HasNoException)
6 {
7 Console.WriteLine("Result was: " + result.Value);
8 }
9 else
10 {
11 if (result.HasFaultExceptionOfType<MyCustomException>())
12 {
13 Console.WriteLine("Service operation threw a custom fault: " + result.Exception.ToString());
14 }
15 else if (result.HasFaultException)
16 {
17 Console.WriteLine("Service operation threw a fault: " + result.Exception.ToString());
18 }
19 else
20 {
21 Console.WriteLine("An unexpected error occurred while calling the service operation: " + result.Exception.ToString());
22 }
23 }
24}
If you generated async Task methods with your service client, and if you call those async Task methods with Consume(), the task will be executed immediately/synchronously.
The ConsumeAsync Method
Use ConsumeAsync() to asynchronously execute async Task methods on your service client. The syntax is the same as the Consume() example above.
Sample Usage Code
For more sample code, please see SampleUsage.cs.
comments powered by Disqus