Web Services 和WCF技术分析之反射

1,二者的区别。前端

WCF能够不依赖于IIS。程序员

WCF能够配置成BasicHttpBinding来兼容(或者说变身成)WS。
WCF能够基于TCP或者MessegeQueue来传输数据。
WCF的可配置性比WS强,好比安全性。
WCF能够是有状态的,并支持事务。
WCF 支持多种通讯协议 Http/Https 、TCP/UDP、MSMQ、命名管道、对等网、
  消息可达性、事务流等。
WCF 能够与ASP.NET 集成、共享一个上下文(HttpContext)。
WCF 支持多种消息传输格式 :text,binary,mtom,Json 等。
WCF 安全性要强:支持对称安全、非对称安全、消息安全、传输安全、
  SSL 流安全、Windows 流安全等。
WCF 支持多种会话模式:单向、双向、请求/响应。
WCF 支持REST 。
WCF 支持多种格式化方式。DataContractSerializer、XmlSerializer、 
  DataContractJsonSerializer 等。
WCF 支持 WAS hosting、Windows 服务 hosting、Self-Hosting、IIS hosting 等。
WCF 支持多种并发模式:单例、单调、会话 web

2,这里要讲的是经过纯运行时代理实现方法的调用。主要用到的技术是反射。编程

一,web servicesjson

private object agent;安全

        private Type agentType;并发

        private const string CODE_NAMESPACE = "Demo";ide

        /// <summary<  函数

        /// 构造函数  性能

        /// </summary<  

        /// <param name="url"<</param<  

        public WebServiceAgent(string url)

        {

            try

            {

              

                XmlTextReader reader = new XmlTextReader(url + "?wsdl");

 

                //建立和格式化 WSDL 文档  

 

                System.Web.Services.Description.ServiceDescription sd = System.Web.Services.Description.ServiceDescription.Read(reader);

 

                //建立客户端代理代理类  

                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();

                sdi.AddServiceDescription(sd, null, null);

 

                //使用 CodeDom 编译客户端代理类  

                CodeNamespace cn = new CodeNamespace(CODE_NAMESPACE);

                CodeCompileUnit ccu = new CodeCompileUnit();

                ccu.Namespaces.Add(cn);

                sdi.Import(cn, ccu);

                Microsoft.CSharp.CSharpCodeProvider icc = new Microsoft.CSharp.CSharpCodeProvider();

                CompilerParameters cp = new CompilerParameters();

                CompilerResults cr = icc.CompileAssemblyFromDom(cp, ccu);

                agentType = cr.CompiledAssembly.GetTypes()[0];

                agent = Activator.CreateInstance(agentType);

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

实现思路:利用wsdl生成xml文档,利用反射生成客户端代理 agent = Activator.CreateInstance(agentType);

二,WCF,引用WCF服务,网上可以找到详细的例子,但都集中于两种方式,1,添加服务引用,这样每次服务变动,须要更新一下引用。2,经过ChannelFactory快速绑定一个终结点,但也须要客户端代理(契约)。WCF一个好处是它是基于契约的,意思是我无论里面如何实现,客户端只关心契约的结果。在构建复杂应用场景中,如何让咱们代码高内聚,低耦合,有同窗说了能够面向接口编程呀,诚然,WCF实现了,这是终极解决方案么?固然不是,假如接口变更了么?相信这是全部程序员的噩梦。.net用反射机制来解决此类问题,全部操做动态生成,这样,咱们不用在关心服务端的变动会影响到客户端。只需阅读接口文档,这样咱们关心的问题转移到配置文件。这种方式会牺牲一些性能(反射),这里咱们须要在性能和便于维护以前平衡了。

  public WebServiceAgent(string url,string aa)

        {

            try

            {

                //获取WSDL

                WebClient wc = new WebClient();

                Stream stream = wc.OpenRead(url + "?singleWsdl");

                  System.Web.Services.Description.ServiceDescription sd = System.Web.Services.Description.ServiceDescription.Read(stream);

                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();

                sdi.AddServiceDescription(sd, "", "");

                CodeNamespace cn = new CodeNamespace(CODE_NAMESPACE);

                //生成客户端代理类代码

                CodeCompileUnit ccu = new CodeCompileUnit();

                ccu.Namespaces.Add(cn);

                sdi.Import(cn, ccu);

                CodeDomProvider provider = new CSharpCodeProvider();//设定编译参数

                CompilerParameters cplist = new CompilerParameters();

                cplist.GenerateExecutable = false;

                cplist.GenerateInMemory = true;

                cplist.ReferencedAssemblies.Add("System.dll");

                cplist.ReferencedAssemblies.Add("System.XML.dll");

                cplist.ReferencedAssemblies.Add("System.Web.Services.dll");

                cplist.ReferencedAssemblies.Add("System.Data.dll");

                //编译代理类

                CompilerResults cr = provider.CompileAssemblyFromDom(cplist, ccu);

                if (true == cr.Errors.HasErrors)

                {

                    System.Text.StringBuilder sb = new System.Text.StringBuilder();

                    foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)

                    {

                        sb.Append(ce.ToString());

                        sb.Append(System.Environment.NewLine);

                    }

                    throw new Exception(sb.ToString());

                }

                //生成代理实例

                agentType = cr.CompiledAssembly.GetTypes()[0];

                agent = Activator.CreateInstance(agentType);

                EndpointAddress address = new EndpointAddress("http://localhost:6666/UserInfo/");

                WSHttpBinding binding = new WSHttpBinding();

               

            }

            catch (Exception ex)

            {

                throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));

            }

        }

原理同web services。

3,经过代理调用方法,这里主要介绍WCF,由于没有亲自编码,后面不对webservices在作介绍。

  public object Invoke(string methodName, params object[] args)

        {

            MethodInfo mi = agentType.GetMethod(methodName);

            try

            {

                var ret = this.Invoke(mi, args);

                var ds = new DataContractJsonSerializer(ret.GetType());

                var ms = new MemoryStream();

                ds.WriteObject(ms, ret);

                var strJSON = Encoding.UTF8.GetString(ms.ToArray());

                ms.Close();

                return strJSON;

            }

            catch (Exception e)

            {

                return e.Message;

            }

            

        }

这里我默认返回是一个集合,由于客户端不清楚返回集合的结构,而咱们又不想编写多余的客户端脚本,这里经过DataContractJsonSerializer实现到json的转换。这个前提是服务端实体类经过[DataContract]标记为可被序列化。

        ///<summary<  

        ///调用指定方法  

        ///</summary<  

        ///<param name="method"<方法信息</param<  

        ///<param name="args"<参数,按照参数顺序赋值</param<  

        ///<returns<Web服务的返回值</returns<  

        public object Invoke(MethodInfo method, params object[] args)

        {

            try

            {

                return method.Invoke(agent, args);

            }

            catch (Exception e)

            {

                return e.Message;

            }

           

        }

4,关于WCF传递参数问题,因为没有客户端代理是动态建立的,咱们用 object[] args存放参数。

服务端代码:

        [OperationContract]

        LoginCheckResult CheckLogin(string userName, string authorizationCode);

客户端调用:

   object[] args = new object[2];

           // args[0] = rtbSend.Text;

            args[0] = "superadmin";

            args[1] = "aaa";

           var  receive =  service.Invoke(methodName, args).ToString() ;

这里service是上面咱们动态生成的代理,methodName是咱们动态解析出来的方法名--CheckLogin

近年来REST风格服务很是流行,这种松散的接口是前端界的一股清流,所到之处,无不夸赞,传统的Web Services和WCF备受歧视,轻量级和安全将是将来主导面向服务编程的两大特性

相关文章
相关标签/搜索