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

  • 相关阅读:
    计算1至n中数字X出现的次数
    DOM处理
    SQL Server中日志
    怎样玩转千万级别的数据
    协议的分用以及wireshark对协议的识别
    序列化json对象,通过ajax传入asp.net mvc后台
    新时代的Vim C++自动补全插件 clang_complete
    ASP.NET Web API 接口执行时间监控
    应用之星在线app开发平台,菜鸟也会做应用
    1.11 查找空值
  • 原文地址:https://www.cnblogs.com/felixnet/p/wcf_client_transparent_proxy_channelfactory.html
Copyright © 2011-2022 走看看