Developers like to write as short and simple code as possible. We are invoking WCF services in C# and wondering if the following intuition is right or wrong.
One way of using ChannelFactory
code is:
var factory = new ChannelFactory<IService>("Endpoint");
var client = factory.CreateChannel();
client.DoSomething();
((IClientChannel)client).Close();
factory.Close();
Other way (a bit cleaner) is using a wrapper object (for factory and channel) which implements IDisposable
where disposes both and used in using block:
using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
svcWrapper.Channel.DoSomething();
}
Here, having to call the wrapper's property might be a bit annoying for developers. Basically also could be:
using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
IService client = svcWrapper.Channel;
client.DoSomething();
}
(I also found this MSDN article saying that the using block can hide exceptions)
What the developers might prefer is:
IService client = new ServiceWrapper<IService>("Endpoint").Channel;
client.DoSomething();
From the book C# 5.0 in a Nutshell:
A popular pattern is to have the finalizer call Dispose. This makes sense when cleanup is non-urgent and hastening it by calling Dispose is more of an optimization than a necessity.
If I add this to my ServiceWrapper
(C# Finalize/Dispose pattern):
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
~ServiceWrapper() {
Dispose(false);
}
Then GC will eventually call Dispose and do the things that need to be done. i.e.:
public void Dispose(bool disposing) {
if (disposing) {
if (_channel != null) {
((IClientChannel)_channel).Close();
}
if (_factory != null) {
_factory.Close();
}
_channel = null;
_factory = null;
}
}
I have a feeling that this is not a good practice to use with WCF ChannelFactory<T>
and T
channel, but I don't have a good explanation which would scare the developers away form using it. Can you guys explain pls?
I can't say it's not working, I tried it and it works fine. I can't see any noticeable performance difference or similar... I cannot give other explanation than "You don't know when the finalizer gets called." Thanks!
Anyone utilizing the client can wrap it into an ordinary using block. If the client is in a clean state a graceful close is done. If the client is in a faulted state a hard abort is done. If an exception is thrown by a service method the client is placed in the faulted state.
Channels provide a low-level programming model for sending and receiving messages. This programming model relies on several interfaces and other types collectively known as the WCF channel model.
Well, the only thing the Dispose
method does is explicitly close the connection. That is all. You can see for yourself in the reference source. Also, ClientBase<T>
, the base class for the connection does the same.
That said, if you call Close
yourself there isn't an actual need at the moment to call Dispose
at all, although I would argue that you really should Dispose
, just to be future proof. Also this can be a fail-safe for errors occurring which may prevent Close
to be called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With