zoukankan      html  css  js  c++  java
  • WCF透明代理类,动态调用,支持async/await

    我们希望WCF客户端调用采用透明代理方式,不用添加服务引用,也不用Invoke的方式,通过ChannelFactory<>动态产生通道,实现服务接口进行调用,并且支持async/await,当然也不用在Config中配置serviceModel。

    服务端代码:

    [ServiceContract]
    public interface IGameService
    {
        [OperationContract]
        Task DoWorkAsync(string arg);
    
        [OperationContract]
        void DoWork(string arg);
    }
    
    public class GameService : IGameService
    {
        public async Task<string> DoWorkAsync(string arg)
        {
            return await Task.FromResult($"Hello {arg}, I am the GameService.");
        }
        public string DoWork(string arg)
        {
            return $"Hello {arg}, I am the GameService.";
        }
    }
    
    [ServiceContract]
    public interface IPlayerService
    {
        [OperationContract]
        Task<string> DoWorkAsync(string arg);
    
        [OperationContract]
        string DoWork(string arg);
    }
    
    public class PlayerService : IPlayerService
    {
        public async Task<string> DoWorkAsync(string arg)
        {
            return await Task.FromResult($"Hello {arg}, I am the PlayerService.");
        }
        public async string DoWork(string arg)
        {
            return $"Hello {arg}, I am the PlayerService.";
        }
    }

    代理类

    动态创建服务对象,ChannelFactory<T>的运用,一个抽象类

    namespace Wettery.Infrastructure.Wcf
    {
        public enum WcfBindingType
        {
            BasicHttpBinding,
            NetNamedPipeBinding,
            NetPeerTcpBinding,
            NetTcpBinding,
            WebHttpBinding,
            WSDualHttpBinding,
            WSFederationHttpBinding,
            WSHttpBinding
        }
    
        public abstract class WcfChannelClient<TChannel> : IDisposable
        {
            public abstract string ServiceUrl { get; }
    
            private Binding _binding;
            public virtual Binding Binding
            {
                get
                {
                    if (_binding == null)
                        _binding = CreateBinding(WcfBindingType.NetTcpBinding);
    
                    return _binding;
                }
            }
    
            protected TChannel _channel;
            public TChannel Channel
            {
                get { return _channel; }
            }
            protected IClientChannel ClientChannel
            {
                get { return (IClientChannel)_channel; }
            }
    
            public WcfChannelClient()
            {
                if (string.IsNullOrEmpty(this.ServiceUrl)) throw new NotSupportedException("ServiceUrl is not overridden by derived classes.");
                var chanFactory = new ChannelFactory<TChannel>(this.Binding, this.ServiceUrl);
                _channel = chanFactory.CreateChannel();
                this.ClientChannel.Open();
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if (disposing && this.ClientChannel != null)
                {
                    try
                    {
                        this.ClientChannel.Close(TimeSpan.FromSeconds(2));
                    }
                    catch
                    {
                        this.ClientChannel.Abort();
                    }
                }
    
                //TODO: free unmanaged resources
            }
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
            ~WcfChannelClient()
            {
                Dispose(false);
            }
    
            private static Binding CreateBinding(WcfBindingType binding)
            {
                Binding bindinginstance = null;
                if (binding == WcfBindingType.BasicHttpBinding)
                {
                    BasicHttpBinding ws = new BasicHttpBinding();
                    ws.MaxBufferSize = 2147483647;
                    ws.MaxBufferPoolSize = 2147483647;
                    ws.MaxReceivedMessageSize = 2147483647;
                    ws.ReaderQuotas.MaxStringContentLength = 2147483647;
                    ws.CloseTimeout = new TimeSpan(0, 10, 0);
                    ws.OpenTimeout = new TimeSpan(0, 10, 0);
                    ws.ReceiveTimeout = new TimeSpan(0, 10, 0);
                    ws.SendTimeout = new TimeSpan(0, 10, 0);
                    bindinginstance = ws;
                }
                else if (binding == WcfBindingType.NetNamedPipeBinding)
                {
                    NetNamedPipeBinding ws = new NetNamedPipeBinding();
                    ws.MaxReceivedMessageSize = 65535000;
                    bindinginstance = ws;
                }
                else if (binding == WcfBindingType.NetPeerTcpBinding)
                {
                    //NetPeerTcpBinding ws = new NetPeerTcpBinding();
                    //ws.MaxReceivedMessageSize = 65535000;
                    //bindinginstance = ws;
                    throw new NotImplementedException();
                }
                else if (binding == WcfBindingType.NetTcpBinding)
                {
                    NetTcpBinding ws = new NetTcpBinding();
                    ws.MaxReceivedMessageSize = 65535000;
                    ws.Security.Mode = SecurityMode.None;
                    bindinginstance = ws;
                }
                else if (binding == WcfBindingType.WebHttpBinding)
                {
                    WebHttpBinding ws = new WebHttpBinding(); //Restful style
                    ws.MaxReceivedMessageSize = 65535000;
                    bindinginstance = ws;
                }
                else if (binding == WcfBindingType.WSDualHttpBinding)
                {
                    WSDualHttpBinding ws = new WSDualHttpBinding();
                    ws.MaxReceivedMessageSize = 65535000;
                    bindinginstance = ws;
                }
                else if (binding == WcfBindingType.WSFederationHttpBinding)
                {
                    WSFederationHttpBinding ws = new WSFederationHttpBinding();
                    ws.MaxReceivedMessageSize = 65535000;
                    bindinginstance = ws;
                }
                else if (binding == WcfBindingType.WSHttpBinding)
                {
                    WSHttpBinding ws = new WSHttpBinding(SecurityMode.None);
                    ws.MaxReceivedMessageSize = 65535000;
                    ws.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
                    ws.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
                    bindinginstance = ws;
                }
                return bindinginstance;
    
            }        
        }
    }
    View Code

    针对每个WCF服务派生一个代理类,在其中重写ServiceUrl与Binding,ServiceUrl可以配置到Config中,Binding不重写默认采用NetTcpBinding

    public class GameServiceClient : WcfChannelClient<IGameService>
        {
            public override string ServiceUrl
            {
                get
                {
                    return "net.tcp://localhost:21336/GameService.svc";
                }
            }
        }
    
    public class PlayerServiceClient : WcfChannelClient<IPlayerService>
        {
            public override string ServiceUrl
            {
                get
                {
                    return "net.tcp://localhost:21336/PlayerService.svc";
                }
            }
        }

    客户端调用

    using (var client = new GameServiceClient())
    {
        client.Channel.DoWork("thinkpig");  //无返回值
        await client.Channel.DoWorkAsync("thinkpig");  //无返回值异步
    }
    
    using (var client = new PlayerServiceClient())
    {
        var result = client.Channel.DoWork("thinkdog");  //有返回值
        result = await client.Channel.DoWorkAsync("thinkdog");  //有返回值异步
    }

    关于WCF寄宿主机可以参考前两篇文章

    WCF绑定netTcpBinding寄宿到控制台应用程序

    WCF绑定netTcpBinding寄宿到IIS

  • 相关阅读:
    盒子垂直水平居中
    Sahi (2) —— https/SSL配置(102 Tutorial)
    Sahi (1) —— 快速入门(101 Tutorial)
    组织分析(1)——介绍
    Java Servlet (1) —— Filter过滤请求与响应
    CAS (8) —— Mac下配置CAS到JBoss EAP 6.4(6.x)的Standalone模式(服务端)
    JBoss Wildfly (1) —— 7.2.0.Final编译
    CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服务端)
    CAS (6) —— Nginx代理模式下浏览器访问CAS服务器网络顺序图详解
    CAS (5) —— Nginx代理模式下浏览器访问CAS服务器配置详解
  • 原文地址:https://www.cnblogs.com/felixnet/p/wcf_client_transparent_proxy_channelfactory.html
Copyright © 2011-2022 走看看