c# - Tricky IDisposable Issue -


i'm trying abstract/encapsulate following code client calls don't need repeat code. example, call, view model (mvvm) 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 @ refactoring this:

public static class prestowcf {     public static iprestoservice prestoservice     {                 {             using (var channelfactory = new wcfchannelfactory<iprestoservice>(new nettcpbinding()))             {                 var endpointaddress = configurationmanager.appsettings["prestoserviceaddress"];                     return channelfactory.createchannel(new endpointaddress(endpointaddress));             }         }     } } 

this allows view models make call 1 line of code now:

this.applications = new observablecollection<application>(prestowcf.prestoservice.getallapplications().tolist()); 

however, error the wcfchannelfactory disposed. makes sense because disposed when view model tries use it. but, if removing using, i'm not disposing of wcfchannelfactory. note, wcfchannelfactory embeds in wcfclientproxy when createchannel() called. why/how view model trying use after has been disposed.

how abstract code, keep view model calls simple possible, while disposing wcfchannelfactory? hope explained enough.

edit - solved!

based on steaks answer, 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 view model call:

this.applications = new observablecollection<application>(prestowcf.invoke(service => service.getallapplications()).tolist()); 

something following may

public static void useprestoservice(action<iprestoservice> callback) {     using (var channelfactory = new wcfchannelfactory<iprestoservice>(new nettcpbinding()))     {         var endpointaddress = configurationmanager.appsettings["prestoserviceaddress"];         iprestoservice prestoservice = channelfactory.createchannel(new endpointaddress(endpointaddress));           //now have access service before channel factory disposed.  don't have worry disposing channel factory.         callback(prestoservice);     } }  useprestoservice(service => this.applications = new observablecollection<application>(service.getallapplications().tolist())); 

side note:

i haven't used pattern disposables because haven't found of need disposables recently. however, in theory think pattern, taking callback executes inside of using block, when working disposables 2 reasons:

  1. it's simple
  2. it forces consumers of idisposables dispose of instances correctly...although agree (i think) c#'s team not raise compiler warnings when idisposables aren't disposed of in execution paths, it's still bit worrisome.

Comments