开发人员喜欢尽可能简短地编写代码.我们在C#中调用WCF服务,并想知道以下直觉是对还是错.使用ChannelFactory代码的一种方法是:
var factory = new ChannelFactory<IService>("Endpoint");
var client = factory.CreateChannel();
client.DoSomething();
((IClientChannel)client).Close();
factory.Close();
Run Code Online (Sandbox Code Playgroud)
其他方式(更清洁一点)是使用包装器对象(用于工厂和通道),它实现了IDisposable两者的配置并在使用块时使用:
using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
svcWrapper.Channel.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
在这里,不得不调用包装器的属性对开发人员来说可能有点烦人.基本上也可能是:
using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
IService client = svcWrapper.Channel;
client.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
(我也发现这篇MSDN文章说使用块可以隐藏异常)
开发人员可能更喜欢的是:
IService client = new ServiceWrapper<IService>("Endpoint").Channel;
client.DoSomething();
Run Code Online (Sandbox Code Playgroud)
从Nutshell中的C#5.0一书:
一种流行的模式是让终结器调用Dispose.当清理非紧急并通过调用来加速它时,这是有道理的.更多的是优化而非必需.
如果我将它添加到我的ServiceWrapper(C#Finalize/Dispose模式):
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
~ServiceWrapper() {
Dispose(false);
}
Run Code Online (Sandbox Code Playgroud)
然后GC最终会调用Dispose并完成需要完成的事情.即:
public void Dispose(bool disposing) {
if (disposing) {
if (_channel != null) {
((IClientChannel)_channel).Close();
}
if (_factory != null) {
_factory.Close();
}
_channel = null;
_factory = null;
}
}
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,这不适合与WCF ChannelFactory<T>和T频道一起使用,但我没有一个很好的解释,它会吓跑开发人员使用它.你能解释一下吗?
我不能说它不起作用,我试过它并且工作正常.我看不出任何明显的性能差异或类似的...我不能给出其他解释而不是"你不知道何时调用终结器". 谢谢!
嗯,该Dispose方法唯一做的是明确关闭连接.就这些.您可以在参考源中看到自己.此外,ClientBase<T>连接的基类也是如此.
也就是说,如果你打电话给Close自己,目前根本没有实际需要打电话Dispose,虽然我认为你真的应该Dispose,只是为了将来证明.对于可能阻止Close被调用的错误,这也可以是故障安全的.