I'm trying to abstract/encapsulate the following code so all client calls don't need to repeat this code. For example, this is a call, from a view model (MVVM) to a WCF service:
using (var channelFactory = new WcfChannelFactory<IPrestoService>(new NetTcpBinding()))
{
var endpointAddress = ConfigurationManager.AppSettings["prestoServiceAddress"];
IPrestoService prestoService = channelFactory.CreateChannel(new EndpointAddress(endpointAddress));
this.Applications = new ObservableCollection<Application>(prestoService.GetAllApplications().ToList());
}
My original attempt at refactoring was to do this:
public static class PrestoWcf
{
public static IPrestoService PrestoService
{
get
{
using (var channelFactory = new WcfChannelFactory<IPrestoService>(new NetTcpBinding()))
{
var endpointAddress = ConfigurationManager.AppSettings["prestoServiceAddress"];
return channelFactory.CreateChannel(new EndpointAddress(endpointAddress));
}
}
}
}
This allows my view models to make the call with just one line of code now:
this.Applications = new ObservableCollection<Application>(PrestoWcf.PrestoService.GetAllApplications().ToList());
However, I get an error the the WcfChannelFactory
is already disposed. This makes sense because it really is disposed when the view model tries to use it. But, if I removing the using
, then I'm not properly disposing of the WcfChannelFactory
. Note, the WcfChannelFactory
embeds itself in the WcfClientProxy
when CreateChannel()
is called. This is why/how the view model is trying to use it after it has been disposed.
How do I abstract this code, to keep my view model calls as simple as possible, while properly disposing WcfChannelFactory
? I hope I explained this well enough.
Edit - Solved!
Based on steaks answer, this did it:
public static class PrestoWcf
{
public static T Invoke<T>(Func<IPrestoService, T> func)
{
using (var channelFactory = new WcfChannelFactory<IPrestoService>(new NetTcpBinding()))
{
var endpointAddress = ConfigurationManager.AppSettings["prestoServiceAddress"];
IPrestoService prestoService = channelFactory.CreateChannel(new EndpointAddress(endpointAddress));
return func(prestoService);
}
}
}
And here is the view model call:
this.Applications = new ObservableCollection<Application>(PrestoWcf.Invoke(service => service.GetAllApplications()).ToList());