是否有可能在Service类中去掉TClient泛型类型?

本文关键字:TClient 泛型类型 有可能 Service 是否 | 更新日期: 2023-09-27 18:04:54

对于WCF客户机,我有一个IServiceProxyFactory接口来设置凭据。

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> { 
    // ... 
} 

从问题是什么是WCF客户端'使用'块问题的最佳解决方案?,我创建了一个助手,如下所示:

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()); 
    

    (更新)

    Service<ServiceClient1>.Use(svc => svc.Method()); 
    
  2. 是否有比Close()Abort()使用ICommunicationObject更好的方法?

是否有可能在Service类中去掉TClient泛型类型?

  • 代码
    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 +,ServiceProxyCommunicationObject衍生而来;然后对于有比…更好的方法吗?的东西,它实现了IDisposible

  5. 对于继承ServiceProxy的具体类的静态实例,每个实例只有一个实例,并存储在m_List中,调用GetServiceProxy<T>()的静态泛型版本只是获取它们。这个看起来更像是轻量级的图案。

  6. 根据5,接口IServiceProxyFactory<T>根本没有使用,只是把它放在那里看,感觉很开心。

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

  8. Use方法中,创建的客户端与using语句一起使用。我已经阅读了Using语句的避免问题,但似乎我不知道你想处理异常的策略,因此我只是尝试重新抛出

  9. 根据1,我认为一个线程安全的方式通过锁自动处置,继承IsDisposedThisLock被使用。CloseAbort在那里做相应的事情。

  10. 哦十!ServiceProxy2ServiceProxy1类仅供示例,ServiceProxy2派生自ServiceProxy1

代码看起来冗长,但实际上非常简单的设计。只要把问题报告给我,我会尽力改正的。希望帮助andgood 锁定!

我通过使用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());