2013-03-21 76 views
2

对于WCF客户端,我有一个IServiceProxyFactory接口来设置凭据。是否有可能摆脱服务类中的TClient泛型类型

public interface IServiceProxyFactory<T> 
{ 
    T GetServiceProxy(); 
} 

public class ServiceProxy1 : IServiceProxyFactory<ServiceClient1> 
{ 
    public ServiceClient1 GetServiceProxy() 
    { 
     var client = new ServiceClient1(); 
     // set credentials here 
     return client; 
    } 
} 

public class ServiceProxy2 : IServiceProxyFactory<ServiceClient2> { 
    // ... 
} 

从问题What is the best workaround for the WCF client `using` block issue?,我创建了一个帮手如下:

public static class Service<TProxy, TClient> 
    where TProxy : IServiceProxyFactory<TClient>, new() 
    where TClient : ICommunicationObject 
{ 
    public static IServiceProxyFactory<TClient> proxy = new TProxy(); 

    public static void Use(Action<TClient> codeBlock) 
    { 
     TClient client = default(TClient); 
     bool success = false; 
     try 
     { 
      client = proxy.GetServiceProxy(); 
      codeBlock(client); 
      ((ICommunicationObject)client).Close(); 
      success = true; 
     } 
     finally 
     { 
      if (!success) 
      { 
       ((ICommunicationObject)client).Abort(); 
      } 
     } 
    } 
} 

我使用助手为:

Service<ServiceProxy1, ServiceClient1>.Use(svc => svc.Method()); 

问:

  1. 有没有办法可以摆脱TClientTProxy(更新)型的,这样我可以调用使用:

    Service<ServiceProxy1>.Use(svc => svc.Method()); 
    

    OR (更新)

    Service<ServiceClient1>.Use(svc => svc.Method()); 
    
  2. 有没有更好的办法,而不是使用ICommunicationObjectClose()Abort()

+0

嗯......你可以改变类上的约束是IServiceProxy ,从类签名删除TClient,并添加TClient和该方法的约束? – JerKimball 2013-03-24 02:12:26

回答

1

我通过使用ServiceClient1 : IServiceProxyFactory<ServiceClient1>的招数将ServiceProxy1类合并到ServiceClient1中实现了它。

public interface IServiceProxyFactory<T> 
{ 
    // can have a better name like SetCredentials() 
    T GetServiceProxy(); 
} 

// Got rid of ServiceProxy1 class 
public partial class ServiceClient1 : IServiceProxyFactory<ServiceClient1> 
{ 
    public ServiceClient1 GetServiceProxy() 
    { 
     var client = this; 
     // set credentials here 
     //client.ClientCredentials = ""; 
     return client; 
    } 
} 

public partial class ServiceClient2 : IServiceProxyFactory<ServiceClient2> { ... } 

public static class ServiceMod<TClient> 
    where TClient : class, ICommunicationObject, IServiceProxyFactory<TClient>, new() 
{ 
    public static TReturn Use<TReturn>(Func<TClient, TReturn> codeBlock) 
    { 
     TClient client = default(TClient); 
     bool success = false; 
     try 
     { 
      client = new TClient().GetServiceProxy(); 
      TReturn result = codeBlock(client); 
      client.Close(); 
      success = true; 
      return result; 
     } 
     finally 
     { 
      if (!success) 
      { 
       client.Abort(); 
      } 
     } 
    } 
} 

现在我可以这样做:

Service<ServiceClient1>.Use(svc => svc.Method()); 
+0

感谢您的赏金,成为一名自学者也很好。此外,我实际上首先发现它应该是'Service 。使用(svc => svc.Method());'因为在原始问题中签署了'Action '。所以我认为唯一可能的事情是'ServiceProxy'和'ServiceClient'是一回事。 – 2013-03-25 11:02:44

3
  • 代码

    partial class TestClass { 
        public static void TestMethod() { 
         Service<ServiceProxy1>.Use(svc => svc.Method()); 
         Service<ServiceProxy1>.Use(svc => svc.Method()); 
         Service<ServiceProxy1>.Use(svc => svc.Method()); 
         Service<ServiceProxy2>.Use(svc => svc.Method()); 
        } 
    } 
    
    public partial interface IServiceProxyFactory<T> { 
        T GetServiceProxy(); 
    } 
    
    public partial class Service<T> where T: ServiceProxy, new() { 
        public static void Use(Action<T> codeBlock) { 
         using(var client=ServiceProxy.GetServiceProxy<T>().GetServiceProxy() as T) 
          try { 
           codeBlock(client); 
          } 
          catch { 
           throw; 
          } 
        } 
    } 
    
    public abstract partial class ServiceProxy: CommunicationObject, IDisposable { 
        public static T GetServiceProxy<T>() where T: ServiceProxy, new() { 
         var proxy=m_List.FirstOrDefault(x => typeof(T).Equals(x.GetType())) as T; 
    
         if(null==proxy) { 
          proxy=new T(); 
          m_List.Add(proxy); 
         } 
    
         return proxy; 
        } 
    
        public abstract ServiceProxy GetServiceProxy(); 
        public abstract void Method(); 
    
        protected virtual void Dispose(bool disposing) { 
         lock(ThisLock) 
          if(!this.IsDisposed&&disposing) { 
           this.Close(); 
    
           if(!this.IsDisposed) 
            this.Abort(); 
          } 
        } 
    
        public void Dispose() { 
         this.Dispose(true); 
         GC.SuppressFinalize(this); 
        } 
    
        ~ServiceProxy() { 
         this.Dispose(false); 
        } 
    
        static List<ServiceProxy> m_List=new List<ServiceProxy>(); 
    } 
    
    public partial class ServiceProxy1: ServiceProxy { 
        protected override IAsyncResult OnBeginClose(
         TimeSpan timeout, AsyncCallback callback, object state 
         ) { 
         throw new NotImplementedException(); 
        } 
    
        protected override IAsyncResult OnBeginOpen(
         TimeSpan timeout, AsyncCallback callback, object state 
         ) { 
         throw new NotImplementedException(); 
        } 
    
        protected override void OnAbort() { 
        } 
    
        protected override void OnEndClose(IAsyncResult result) { 
        } 
    
        protected override void OnEndOpen(IAsyncResult result) { 
        } 
    
        protected override void OnClose(TimeSpan timeout) { 
        } 
    
        protected override void OnOpen(TimeSpan timeout) { 
        } 
    
        protected override TimeSpan DefaultCloseTimeout { 
         get { 
          return TimeSpan.Zero; 
         } 
        } 
    
        protected override TimeSpan DefaultOpenTimeout { 
         get { 
          return TimeSpan.Zero; 
         } 
        } 
    
        public override ServiceProxy GetServiceProxy() { 
         var client=new ServiceProxy1(); 
         // set credentials here 
         return client; 
        } 
    
        public override void Method() { 
        } 
    } 
    
    public partial class ServiceProxy2: ServiceProxy1 { 
        public override ServiceProxy GetServiceProxy() { 
         var client=new ServiceProxy2(); 
         // set credentials here 
         return client; 
        } 
    } 
    

东西说:

  1. lock是安全,可以重新输入

  2. 这是不可能的,我做了逆转推断的完全一样的声明从T到任何类型的Generic<T>,如ServiseClientServiceProxy<ServiceClient>

  3. 根据2,ServiceProxyServiceClient在代码中是一样的,所以没有ServiceClient

  4. ServiceProxy本身是摘要。对于ServiceClient的要求需要转换为ICommunicationObject并且根据3加为了方便的原因,ServiceProxy来自CommunicationObject;然后为难道还有比...的东西,它实现IDisposible

  5. 对于它继承ServiceProxy,混凝土类的静态实例的每位将有只有一个例如一个更好的方式,和存储在m_List,并调用静态通用版本GetServiceProxy<T>()只是让他们。这看起来更像是flyweight模式。

  6. 根据5,界面IServiceProxyFactory<T>根本没有使用,只是把它放在那里看起来很愉快。

  7. GetServiceProxy()的实例版本保持原来的用法,但具体的类将需要覆盖它。

  8. Use方法中,所创建的客户端用于使用语句。我已阅读Avoiding Problems with the Using Statement,但似乎我不知道您想要处理例外的策略,因此我只需尝试重新调整

  9. 根据1,我被锁考虑线程安全方式处置原子,继承IsDisposed和使用ThisLockCloseAbort正在那里做相应的。

  10. 哦十! ServiceProxy2ServiceProxy1仅供参考,ServiceProxy2来自ServiceProxy1

该代码看起来很冗长,但实际上非常简单的设计。只要报告我的问题,我会尽力纠正它。希望有助于和好LOCK

+1

只是供参考:对于第八点:Dispose不应该抛出,甚至更多,你应该可以安全地调用Dispose对已经处置的对象多次处理。没有“使用时隐藏异常”这样的问题 - 问题在于一个Dispose方法无效执行 – quetzalcoatl 2013-03-24 10:02:01

+0

@quetzalcoatl:哦,当然。我主要假设我不知道是否有可能抛出,甚至在处置之前。所以留下一个*尝试和重新抛出*应该是适用的方式。非常感谢你! – 2013-03-24 10:15:14

+0

@KenKin,我最终回答如下。但是你用'偏'来推动我朝着正确的方向前进,所以我要给你赏金。 – hIpPy 2013-03-25 05:27:35

相关问题