2009-07-20 25 views

cevap

4

Bu model ile iyi yaşamadık: Doğru genel bir fikir var

Dim service As New MyService() 
Dim closed As Boolean = False 
Try 
    service.Open() 
    If Not service.State = ServiceModel.CommunicationState.Opened Then 
     ''Handle a not-opened state here 
    End If 
    service.MyMethod() 
    service.Close() 
    closed = true 
Catch ex As Exception 
    ''Handle errors here 
Finally 
    If Not closed Then 
     service.Abort() 
    End If 
End Try 
service = Nothing 
2

. Tekrar eden kod satırlarını minimumda tutmak için aşağıdaki uzantı yöntemini kullandım. Bu uzantı yöntemi kullanarak kod

public static class ICommunicationObjectExtensions 
{  
    public static void SafelyCloseConnection(this ICommunicationObject objectToClose) 
    { 
     bool success = false; 

     try 
     { 
     objectToClose.Close(); 
     success = true; 
     } 
     finally 
     { 
     if (!success) 
     { 
      objectToClose.Abort(); 
     } 
     } 
    } 
} 

Örnek: Elbette

HelloWorldServiceClient client = new HelloWorldServiceClient(); 
HelloWorldDataContract dc = new HelloWorldDataContract(); 

try 
{ 
    client.Open(); 
    dc = client.SayHello(); 
} // Add catch blocks here for anything you want to handle. 
finally 
{ 
    client.SafelyCloseConnection(); 
} 

bu C#, ama hala yardım olması gerektiğini düşünüyorum.

15

bakınız Indisposable: WCF Yakaladım # diye uygun bir sarıcı yöntemi ile çıkageldi 1 *:

public delegate void UseServiceDelegate<T>(T proxy); 

public static class Service<T> 
{ 
    public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>(""); 

    public static void Use(UseServiceDelegate<T> codeBlock) 
    { 
     var proxy = (IClientChannel)_channelFactory.CreateChannel(); 
     var success = false; 
     try 
     { 
      codeBlock((T)proxy); 
      proxy.Close(); 
      success = true; 
     } 
     finally 
     { 
      if (!success) 
      { 
       proxy.Abort(); 
      } 
     } 
    } 
} 

Kullanımı:

Service<IOrderService>.Use(
    orderService => 
     { 
      orderService.PlaceOrder(request); 
     }); 

* bunun yanı kaldırıldı Bağlantı zararlı gibi görünen .

+0

Ben senin çözüm ister, ancak var mı ki Bağımlılık Enjeksiyon ile kullanılabilir. Hizmet bir bağımlılık olduğundan, testimi buna karşı uygulamak istemiyorum. –

+0

Bu benim çözümüm değil. Her durumda, "" Hizmetini statik olmayan hale getirebileceğinizi ve "ChannelFactory " veya "IClientChannel" öğelerini enjekte edebileceğinizi umuyorum. –

0

Bir istemci tarafı önbelleği kullanırsanız, İfade Ağaçlar kullanabilirsiniz (http://thegrenade.blogspot.com/2009/07/using-expression-trees-for-more-elegant.html bakınız):

private static TEntity GetItem<TProxy, TEntity, TIdentity>(Expression<Func<TProxy, TIdentity, TEntity>> expression, TProxy proxy, TIdentity id) 
    where TEntity : class 
    where TProxy : ICommunicationObject 
{ 
    TEntity item = Cache.GetItem<TEntity, TIdentity>(id); 
    if (item == null) 
    { 
     try 
     { 
      var originalDelegate = expression.Compile(); 
      item = originalDelegate.Invoke(proxy, id); 
     } 
     finally 
     { 
      try{ proxy.Close(); } 
      finally { proxy.Abort(); } 
     } 
     Cache.AddItem<TEntity, TIdentity>(item); 
    } 
    return item; 
} 

Kullanımı:

Product p = GetItem((client, identifier) => client.GetProduct(identifier), new CatalogServiceClient(), 123); 
+0

Rob, Cevabınızın bu soru için nasıl geçerli olduğunu göremiyorum. –

+0

Belki de verdiğim yöntem örneği, genel bir servis çağrısı sarıcısı için biraz fazla spesifiktir. Gerçekte, birden fazla parametre alan servis yöntemleri için aşırı yöntemlere gereksiniminiz var ve bu örnek bu ayrıntıya girmiyor. Bununla birlikte, birçok WCF çözümü, bir id parametresiyle elde edilmesine karşılık olarak farklı tipler döndüren çok benzer yöntem gruplarını içerir. Ve son olarak benim blokumun da iptal için iç içe bir deneme/nihayetinde eksik olduğunu biliyorsunuz. – grenade

+0

Sanırım tekrar soruyu okumak zorunda kalabilirsiniz. Cevabınız soruyu hiçbir şekilde ele almıyor. –