<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_JerryShi's blog</title><subtitle type="text">静水流深</subtitle><id>http://feed.cnblogs.com/blog/u/32057/rss</id><updated>2011-12-14T10:20:31Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/32057/rss"/><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/12/14/2287929.html</id><title type="text">使用流模式传输大型数据</title><summary type="text">WCF 支持两种消息处理模式： 缓冲模式：WCF处理消息的默认方式，在缓冲模式下，整个消息都会保存在内存中，知道发送或者接收完成。此模式作为默认方式，在某些情况下是必需的，如可靠消息传送和数字签名，...</summary><published>2011-12-14T10:20:00Z</published><updated>2011-12-14T10:20:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/12/14/2287929.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/12/14/2287929.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;WCF 支持两种消息处理模式：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;缓冲模式：WCF处理消息的默认方式，在缓冲模式下，整个消息都会保存在内存中，知道发送或者接收完成。此模式作为默认方式，在某些情况下是必需的，如可靠消息传送和数字签名，但存在的缺陷是如果消息数据过大，缓冲占用大量系统内存，同时消耗其他系统资源。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;流模式：使用System.IO.Stream 来发传送消息，流模式通常在绑定或传输信道上打开，在绑定的配置上设置transferMode属性来控制流模式的粒度。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;transferMode的属性值包括：Buffer、Streamed、StreamedResponse、StreamedRequest；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;Demo&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt; Contract：&lt;/font&gt;&lt;/p&gt;      [ServiceContract]&lt;br/&gt;    public interface IFileDownload&lt;br/&gt;    {&lt;br/&gt;        [OperationContract]&lt;br/&gt;        Stream GetFileStream(string fileName);&lt;br/&gt;    }&lt;p&gt;&lt;font face="微软雅黑"&gt;Service:&lt;/font&gt;&lt;/p&gt;    public class FileDownloadService : IFileDownload, IDisposable&lt;br/&gt;    {&lt;br/&gt;        private FileStream fStream = null;&lt;br/&gt;&lt;br/&gt;        public Stream GetFileStream(string fileName)&lt;br/&gt;        {&lt;br/&gt;            string filePath = AppDomain.CurrentDomain.BaseDirectory + fileName;&lt;br/&gt;            if (!File.Exists(filePath))&lt;br/&gt;            {&lt;br/&gt;                throw new ArgumentException(string.Format(&amp;quot;无法找到文件名为{0}的文件&amp;quot;, fileName));&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);&lt;br/&gt;            return fStream;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void Dispose()&lt;br/&gt;        {&lt;br/&gt;            Dispose(true);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        protected virtual void Dispose(bool disposing)&lt;br/&gt;        {&lt;br/&gt;            //被客户直接调用的,那么托管的,和非托管的资源都可以释放&amp;#160; if (disposing)&lt;br/&gt;            {&lt;br/&gt;                // 释放 托管资源&amp;#160; fStream.Dispose();&lt;br/&gt;                //垃圾回收器从Finalization队列中清除自己,从而阻止垃圾回收器调用Finalize方法.&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; GC.SuppressFinalize(this);&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;p&gt;&lt;font face="微软雅黑"&gt;Config&lt;/font&gt;&lt;/p&gt;&amp;lt;service name=&amp;quot;JerryShi.EssentialWCF.FileDownloadService&amp;quot;  behaviorConfiguration=&amp;quot;StockServiceBehavior&amp;quot;&amp;gt;&lt;br/&gt;        &amp;lt;host&amp;gt;&lt;br/&gt;          &amp;lt;baseAddresses&amp;gt;&lt;br/&gt;            &amp;lt;add baseAddress=&amp;quot;net.tcp://localhost:809/FileDownloadService&amp;quot;/&amp;gt;&lt;br/&gt;          &amp;lt;/baseAddresses&amp;gt;&lt;br/&gt;        &amp;lt;/host&amp;gt;&lt;br/&gt;        &amp;lt;endpoint address=&amp;quot;&amp;quot; binding=&amp;quot;netTcpBinding&amp;quot;  contract=&amp;quot;JerryShi.EssentialWCF.IFileDownload&amp;quot; bindingConfiguration=&amp;quot;EnableStreamingOnNetTcp&amp;quot; /&amp;gt;&lt;br/&gt;        &amp;lt;endpoint address=&amp;quot;mex&amp;quot; binding=&amp;quot;mexTcpBinding&amp;quot; contract=&amp;quot;IMetadataExchange&amp;quot; /&amp;gt;&lt;br/&gt;      &amp;lt;/service&amp;gt;&lt;br/&gt;    &amp;lt;/services&amp;gt;&lt;br/&gt;    &amp;lt;bindings&amp;gt;&lt;br/&gt;      &amp;lt;netTcpBinding&amp;gt;&lt;br/&gt;        &amp;lt;binding name=&amp;quot;EnableStreamingOnNetTcp&amp;quot; transferMode=&amp;quot;Streamed&amp;quot; /&amp;gt;&lt;br/&gt;      &amp;lt;/netTcpBinding&amp;gt;&lt;br/&gt;    &amp;lt;/bindings&amp;gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;说明&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;运行过程中出现一次异常，异常如下：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201112/201112141819315742.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="error" border="0" alt="error" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201112/201112141819312187.png" width="456" height="270" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;此异常由于Client端配置与Server端配置不匹配导致的&lt;/font&gt;&lt;/p&gt;&amp;lt;binding name=&amp;quot;NetTcpBinding_IFileDownload&amp;quot; closeTimeout=&amp;quot;00:01:00&amp;quot;&lt;br/&gt;                   openTimeout=&amp;quot;00:01:00&amp;quot; receiveTimeout=&amp;quot;00:10:00&amp;quot; sendTimeout=&amp;quot;00:01:00&amp;quot;&lt;br/&gt;                   transactionFlow=&amp;quot;false&amp;quot; transferMode=&amp;quot;Streamed&amp;quot; transactionProtocol=&amp;quot;OleTransactions&amp;quot;&lt;br/&gt;                   hostNameComparisonMode=&amp;quot;StrongWildcard&amp;quot; listenBacklog=&amp;quot;10&amp;quot;&lt;br/&gt;                   maxBufferPoolSize=&amp;quot;524288&amp;quot; maxBufferSize=&amp;quot;65536&amp;quot; maxConnections=&amp;quot;10&amp;quot;&lt;br/&gt;                   maxReceivedMessageSize=&amp;quot;65536&amp;quot;&amp;gt;&lt;br/&gt;          &amp;lt;readerQuotas maxDepth=&amp;quot;32&amp;quot; maxStringContentLength=&amp;quot;8192&amp;quot; maxArrayLength=&amp;quot;16384&amp;quot;&lt;br/&gt;              maxBytesPerRead=&amp;quot;4096&amp;quot; maxNameTableCharCount=&amp;quot;16384&amp;quot; /&amp;gt;&lt;br/&gt;          &amp;lt;reliableSession ordered=&amp;quot;true&amp;quot; inactivityTimeout=&amp;quot;00:10:00&amp;quot;&lt;br/&gt;              enabled=&amp;quot;false&amp;quot; /&amp;gt;&lt;br/&gt;          &amp;lt;security mode=&amp;quot;Transport&amp;quot;&amp;gt;&lt;br/&gt;            &amp;lt;transport clientCredentialType=&amp;quot;Windows&amp;quot; protectionLevel=&amp;quot;EncryptAndSign&amp;quot; /&amp;gt;&lt;br/&gt;            &amp;lt;message clientCredentialType=&amp;quot;Windows&amp;quot; /&amp;gt;&lt;br/&gt;          &amp;lt;/security&amp;gt;&lt;br/&gt;        &amp;lt;/binding&amp;gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2287929.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/12/14/2287929.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/11/19/2254767.html</id><title type="text">对象序列化之 替换（Surrogate）</title><summary type="text">有可能存在一种情况，实体类型无法进行序列化或需要在序列化的方式上进行更改，如 第三方组件供应商提供的类型或者没有源代码的组件。 对于这种情况，WCF提供IDataContractSurrogate 接...</summary><published>2011-11-18T16:28:00Z</published><updated>2011-11-18T16:28:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/11/19/2254767.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/11/19/2254767.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;有可能存在一种情况，实体类型无法进行序列化或需要在序列化的方式上进行更改，如 第三方组件供应商提供的类型或者没有源代码的组件。 对于这种情况，WCF提供IDataContractSurrogate 接口 来实现一个替身类解决此类问题。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;解决问题的步骤：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;1. 定义数据契约来表示序列化的类型；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;2. 定义实现序列化替身的操作类，实现IDataContractSurrogate接口，并至少实现其三个方法： GetDataContractType、GetDeserializedObject、GetObjectToSerialize ，其中GetDataContractType方法会向DataContractSerializer 返回需要序列化的类型，而GetObjectToSerialize和GetDeserializedObject会实际执行序列化和反序列化。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;以下代码：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;假设 Employee 无法实现序列化，以EmployeeSurrogated 作为其替身类，以EmpoyyeeSurrogate实现操作，代码如下：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;EmployeeSurrogated 定义：&lt;/font&gt;&lt;/p&gt;      [DataContract]&lt;br/&gt;    internal class EmployeeSurrogated&lt;br/&gt;    {&lt;br/&gt;        public EmployeeSurrogated(int employeeID, string firstName, string lastName)&lt;br/&gt;        {&lt;br/&gt;            this.employeeID = employeeID;&lt;br/&gt;            this.firstName = firstName;&lt;br/&gt;            this.lastName = lastName;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        private int employeeID;&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        private string firstName;&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        private string lastName;&lt;br/&gt;&lt;br/&gt;        public int EmployeeID&lt;br/&gt;        {&lt;br/&gt;            get { return this.employeeID; }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public string FirstName&lt;br/&gt;        {&lt;br/&gt;            get { return this.firstName; }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public string LastName&lt;br/&gt;        {&lt;br/&gt;            get { return this.lastName; }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;    }&lt;p&gt;&lt;font face="微软雅黑"&gt;EmployeeSurrogate 操作类：&lt;/font&gt;&lt;/p&gt; public class EmployeeSurrogate : IDataContractSurrogate&lt;br/&gt;    {&lt;br/&gt;        public object GetCustomDataToExport(Type clrType, Type dataContractType)&lt;br/&gt;        {&lt;br/&gt;            return null;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)&lt;br/&gt;        {&lt;br/&gt;            return null;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 向DataContractSerializer 返回需要序列化的类型&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name=&amp;quot;type&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br/&gt;        public Type GetDataContractType(Type type)&lt;br/&gt;        {&lt;br/&gt;            if (typeof(Employee).IsAssignableFrom(type))&lt;br/&gt;            {&lt;br/&gt;                return typeof(EmployeeSurrogated);&lt;br/&gt;            }&lt;br/&gt;            return type;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 执行反序列化后应返回的实际类型&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name=&amp;quot;obj&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name=&amp;quot;targetType&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br/&gt;        public object GetDeserializedObject(object obj, Type targetType)&lt;br/&gt;        {&lt;br/&gt;            if (obj is EmployeeSurrogated)&lt;br/&gt;            {&lt;br/&gt;                EmployeeSurrogated oldEmployee = obj as EmployeeSurrogated;&lt;br/&gt;&lt;br/&gt;                Employee newEmployee = new Employee() &lt;br/&gt;                {&lt;br/&gt;                    EmployeeID = oldEmployee.EmployeeID, &lt;br/&gt;                    FirstName = oldEmployee.FirstName, &lt;br/&gt;                    LastName = oldEmployee.LastName &lt;br/&gt;                };&lt;br/&gt;                return newEmployee;&lt;br/&gt;            }&lt;br/&gt;            return obj;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection&amp;lt;Type&amp;gt; customDataTypes)&lt;br/&gt;        {&lt;br/&gt;            throw new NotImplementedException();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        /// &amp;lt;summary&amp;gt;&lt;br/&gt;        /// 将无法序列化的对象转化会替身类性&lt;br/&gt;        /// &amp;lt;/summary&amp;gt;&lt;br/&gt;        /// &amp;lt;param name=&amp;quot;obj&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;param name=&amp;quot;targetType&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;br/&gt;        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br/&gt;        public object GetObjectToSerialize(object obj, Type targetType)&lt;br/&gt;        {&lt;br/&gt;            if (obj is Employee)&lt;br/&gt;            {&lt;br/&gt;                Employee oldEmployee = obj as Employee;&lt;br/&gt;                EmployeeSurrogated newEmployee = new EmployeeSurrogated(oldEmployee.EmployeeID, oldEmployee.FirstName, oldEmployee.LastName);&lt;br/&gt;                return newEmployee;&lt;br/&gt;            }&lt;br/&gt;            return obj;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)&lt;br/&gt;        {&lt;br/&gt;            if (typeNamespace.Equals(@&amp;quot;http://schemas.datacontract.org/2004/07/EmplyeeSurrogated&amp;quot;))&lt;br/&gt;            {&lt;br/&gt;                if (typeName.Equals(&amp;quot;EmployeeSurrogated&amp;quot;))&lt;br/&gt;                {&lt;br/&gt;                    return typeof(Employee);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;            return null;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)&lt;br/&gt;        {&lt;br/&gt;            return typeDeclaration;&lt;br/&gt;        }&lt;br/&gt;    }&lt;p&gt;&lt;font face="微软雅黑"&gt;序列化方式：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;序列化器： 注意 DataContractSerializer 的实例化调用的构造方法，此关键操作导致可以实现替代的序列化；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;        public static string TryToSerialize(object obj)&lt;br/&gt;        {&lt;br/&gt;            DataContractSerializer serializer = new DataContractSerializer(obj.GetType());&lt;br/&gt;            using (StringWriter strWriter = new StringWriter())&lt;br/&gt;            {&lt;br/&gt;                using (XmlWriter xWriter = XmlWriter.Create(strWriter))&lt;br/&gt;                {&lt;br/&gt;                    try&lt;br/&gt;                    {&lt;br/&gt;                        serializer.WriteObject(xWriter, obj);&lt;br/&gt;                        xWriter.Flush();&lt;br/&gt;                        return strWriter.ToString();&lt;br/&gt;                    }&lt;br/&gt;                    catch (Exception ex)&lt;br/&gt;                    {&lt;br/&gt;                        Console.WriteLine(&amp;quot;Can not serialize without a surrogate : {0}&amp;quot;, ex);&lt;br/&gt;                    }&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;            return string.Empty;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static string SerializeUsingSurrogate(object obj, IDataContractSurrogate surrogateObj)&lt;br/&gt;        {&lt;br/&gt;            DataContractSerializer serializer = new DataContractSerializer(obj.GetType(), null, int.MaxValue, false, false, surrogateObj);&lt;br/&gt;&lt;br/&gt;            return SerializeUsingSurrogate(serializer, obj);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static string SerializeUsingSurrogate(DataContractSerializer serializer, object obj)&lt;br/&gt;        {&lt;br/&gt;            using (StringWriter strWriter = new StringWriter())&lt;br/&gt;            {&lt;br/&gt;                using (XmlWriter xWriter = XmlWriter.Create(strWriter))&lt;br/&gt;                {&lt;br/&gt;                    serializer.WriteObject(xWriter, obj);&lt;br/&gt;                    xWriter.Flush();&lt;br/&gt;                    return strWriter.ToString();&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static object DeserializeUsingSurrogate(Type sourceType, IDataContractSurrogate surrogateObj, string objXml)&lt;br/&gt;        {&lt;br/&gt;            DataContractSerializer serializer = new DataContractSerializer(sourceType, null, int.MaxValue, false, false, surrogateObj);&lt;br/&gt;&lt;br/&gt;            return DeserializeUsingSurrogate(serializer, objXml);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static object DeserializeUsingSurrogate(DataContractSerializer serializer, string objXml)&lt;br/&gt;        {&lt;br/&gt;            using (StringReader strReader = new StringReader(objXml))&lt;br/&gt;            {&lt;br/&gt;                using (XmlReader xReader = XmlReader.Create(strReader))&lt;br/&gt;                {&lt;br/&gt;                    return serializer.ReadObject(xReader);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;p&gt;&lt;font face="微软雅黑"&gt;最后执行：&lt;/font&gt;&lt;/p&gt; static void SerializeSurrogate()&lt;br/&gt;        {&lt;br/&gt;            Employee e = new Employee() &lt;br/&gt;            { &lt;br/&gt;                EmployeeID = 1,&lt;br/&gt;                FirstName = &amp;quot;jerry&amp;quot;,&lt;br/&gt;                LastName = &amp;quot;shi&amp;quot;&lt;br/&gt;            };&lt;br/&gt;&lt;br/&gt;            Console.WriteLine(&amp;quot;{0},{1},{2}&amp;quot;, e.EmployeeID, e.FirstName, e.LastName);&lt;br/&gt;&lt;br/&gt;            SerializeHelper.TryToSerialize(e);&lt;br/&gt;&lt;br/&gt;            string objXml = SerializeHelper.SerializeUsingSurrogate(e, new EmployeeSurrogate());&lt;br/&gt;&lt;br/&gt;            Console.WriteLine(objXml);&lt;br/&gt;&lt;br/&gt;            Employee newobj = (Employee)SerializeHelper.DeserializeUsingSurrogate(e.GetType(), new EmployeeSurrogate(), objXml);&lt;br/&gt;&lt;br/&gt;            Console.WriteLine(&amp;quot;{0},{1},{2}&amp;quot;, newobj.EmployeeID, newobj.FirstName, newobj.LastName);&lt;br/&gt;&lt;br/&gt;            Console.WriteLine(&amp;quot;Press &amp;lt;Enter&amp;gt; to continute...&amp;quot;);&lt;br/&gt;            Console.ReadLine();&lt;br/&gt;        }&lt;p&gt;&lt;font face="微软雅黑"&gt;结果说明：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201111/201111190027426966.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="序列化替代结果" border="0" alt="序列化替代结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201111/201111190027438885.png" width="644" height="422" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2254767.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/11/19/2254767.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221733.html</id><title type="text">使用 IExtensibleDataObject 进行往返式序列化</title><summary type="text">数据契约会随着时间的推移不断出现新的版本，结构相同但带有新增信息。与其将使用旧版本的数据契约的客户端与服务全部重新生成编译，不如让新版本向前兼容，使用共有部分的数据。 DataContractSer...</summary><published>2011-10-23T05:27:00Z</published><updated>2011-10-23T05:27:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221733.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221733.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;数据契约会随着时间的推移不断出现新的版本，结构相同但带有新增信息。与其将使用旧版本的数据契约的客户端与服务全部重新生成编译，不如让新版本向前兼容，使用共有部分的数据。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;DataContractSerializer 正式这样处理的，如果消息中有多余的数据，DataContractSerializer会将其丢弃。 不过这样做在有些情况下会出现问题，如果数据被接受之后还要返还给客户端，那么忽略任何多余的数据都有可能造成信息的丢失。这正IExtensibleDataObject 接口要解决的问题，其提供了对数据契约使用未知外部数据的能力，在进行反序列化时，将任何未知的数据都存储在一个ExtensibleDataObject类的实例中。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;DataContractSerializer 默认会忽略任何未被使用或期望的数据，除非在契约上实现了IExtensibleDataObject接口。&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font face="微软雅黑"&gt;可以通过添加程序集的方式不生成代理类就共享数据契约，在这种情况下要确保数据契约实现了IExtensibleDataObject，否则将无法支持往返序列化&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;示例：&lt;/font&gt;&lt;/p&gt;      [DataContract]&lt;br/&gt;    public class Employee : IExtensibleDataObject&lt;br/&gt;    {&lt;br/&gt;        [DataMember]&lt;br/&gt;        public int EmployeeID { get; set; }&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        public string FirstName { get; set; }&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        public string LastName { get; set; }&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        public string SSN { get; set; }&lt;br/&gt;&lt;br/&gt;        private ExtensionDataObject extensionData;&lt;br/&gt;&lt;br/&gt;        public ExtensionDataObject ExtensionData&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.extensionData;&lt;br/&gt;            }&lt;br/&gt;            set&lt;br/&gt;            {&lt;br/&gt;                this.extensionData = value;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;若使用svcutil生成代码，则会自动为客户端生成对应的实体，自动会继承Object，并实现IExtensionDataObject 接口。如：&lt;/font&gt;&lt;/p&gt;   using System.Runtime.Serialization;&lt;br/&gt;    &lt;br/&gt;    &lt;br/&gt;    [System.Diagnostics.DebuggerStepThroughAttribute()]&lt;br/&gt;    [System.CodeDom.Compiler.GeneratedCodeAttribute(&amp;quot;System.Runtime.Serialization&amp;quot;, &amp;quot;4.0.0.0&amp;quot;)]&lt;br/&gt;    [System.Runtime.Serialization.DataContractAttribute(Name=&amp;quot;Employee&amp;quot;, Namespace=&amp;quot;http://schemas.datacontract.org/2004/07/JerryShi.EssentialWCF&amp;quot;)]&lt;br/&gt;    public partial class Employee : object, System.Runtime.Serialization.IExtensibleDataObject&lt;br/&gt;    {&lt;br/&gt;        &lt;br/&gt;        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;&lt;br/&gt;        &lt;br/&gt;        private int EmployeeIDField;&lt;br/&gt;        &lt;br/&gt;        private string FirstNameField;&lt;br/&gt;        &lt;br/&gt;        private string LastNameField;&lt;br/&gt;        &lt;br/&gt;        public System.Runtime.Serialization.ExtensionDataObject ExtensionData&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.extensionDataField;&lt;br/&gt;            }&lt;br/&gt;            set&lt;br/&gt;            {&lt;br/&gt;                this.extensionDataField = value;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;        &lt;br/&gt;        [System.Runtime.Serialization.DataMemberAttribute()]&lt;br/&gt;        public int EmployeeID&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.EmployeeIDField;&lt;br/&gt;            }&lt;br/&gt;            set&lt;br/&gt;            {&lt;br/&gt;                this.EmployeeIDField = value;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;        &lt;br/&gt;        [System.Runtime.Serialization.DataMemberAttribute()]&lt;br/&gt;        public string FirstName&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.FirstNameField;&lt;br/&gt;            }&lt;br/&gt;            set&lt;br/&gt;            {&lt;br/&gt;                this.FirstNameField = value;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;        &lt;br/&gt;        [System.Runtime.Serialization.DataMemberAttribute()]&lt;br/&gt;        public string LastName&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                return this.LastNameField;&lt;br/&gt;            }&lt;br/&gt;            set&lt;br/&gt;            {&lt;br/&gt;                this.LastNameField = value;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2221733.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221733.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221679.html</id><title type="text">使用 NetDataContractSerializer 共享类型</title><summary type="text">在上一章节《WCF可序列化方式》 提到了NetDataContractSerializer 适用于客户端与服务端共享类型信息，支持支持类型不变性。 但并没有提供现成的特性，所以无法使用对数据契约进行标...</summary><published>2011-10-23T03:56:00Z</published><updated>2011-10-23T03:56:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221679.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221679.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;在&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221364.html"&gt;上一章节《WCF可序列化方式》&lt;/a&gt; 提到了NetDataContractSerializer 适用于客户端与服务端共享类型信息，支持支持类型不变性。 但并没有提供现成的特性，所以无法使用对数据契约进行标记的方式来达到使用NetDataContractSerializer的目的，必须通过自定制开发，才能对操作契约进行标注。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;1. NetDataContractFormatAttribute特性；&lt;/font&gt;&lt;/p&gt;      public class NetDataContractFormatAttribute : Attribute, IOperationBehavior&lt;br/&gt;    {&lt;br/&gt;        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)&lt;br/&gt;        {&lt;br/&gt;            ReplaceDataContractSerializerOperationBehavior(operationDescription);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)&lt;br/&gt;        {&lt;br/&gt;            ReplaceDataContractSerializerOperationBehavior(operationDescription);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void Validate(OperationDescription operationDescription)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static void ReplaceDataContractSerializerOperationBehavior(OperationDescription description)&lt;br/&gt;        {&lt;br/&gt;            DataContractSerializerOperationBehavior dcs = description.Behaviors.Find&amp;lt;DataContractSerializerOperationBehavior&amp;gt;();&lt;br/&gt;            &lt;br/&gt;            if (dcs != null)&lt;br/&gt;            {&lt;br/&gt;                description.Behaviors.Remove(dcs);&lt;br/&gt;            }&lt;br/&gt;            description.Behaviors.Add(new NetDataContractSerializerOperationBehavior(description));&lt;br/&gt;        }&lt;br/&gt;    }&lt;p&gt;&lt;font face="微软雅黑"&gt;2. NetDataContractSerializerOperationBehavior 行为；&lt;/font&gt;&lt;/p&gt;    public class NetDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior&lt;br/&gt;    {&lt;br/&gt;        private static NetDataContractSerializer serializer = new NetDataContractSerializer();&lt;br/&gt;&lt;br/&gt;        public NetDataContractSerializerOperationBehavior(OperationDescription operationDescription)&lt;br/&gt;            : base(operationDescription)&lt;br/&gt;        {&lt;br/&gt;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList&amp;lt;Type&amp;gt; knownTypes)&lt;br/&gt;        {&lt;br/&gt;            return NetDataContractSerializerOperationBehavior.serializer;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList&amp;lt;Type&amp;gt; knownTypes)&lt;br/&gt;        {&lt;br/&gt;            return NetDataContractSerializerOperationBehavior.serializer;&lt;br/&gt;        }&lt;br/&gt;    }&lt;p&gt;&lt;font face="微软雅黑"&gt;3. 将特性标记在契约中；&lt;/font&gt;&lt;/p&gt;    [ServiceContract(CallbackContract = typeof(IStockServiceCallback))]&lt;br/&gt;    public interface IStockService&lt;br/&gt;    {        &lt;br/&gt;        [OperationContract]&lt;br/&gt;        double GetPrice(string ticker);&lt;br/&gt;&lt;br/&gt;        [OperationContract(IsOneWay = true)]&lt;br/&gt;        void RegisterForUpdate(string ticker);&lt;br/&gt;&lt;br/&gt;        [OperationContract]&lt;br/&gt;        [NetDataContractFormat]&lt;br/&gt;        StockPrice GetStockPrice(string ticker);&lt;br/&gt;    }&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2221679.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/23/2221679.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221364.html</id><title type="text">WCF可序列化方式</title><summary type="text">WCF支持多种序列化方式，决定使用何种取决于多种因素，包括是否希望共享类型或契约，是否支持现有.net类型，是否保留引用等等。</summary><published>2011-10-22T12:42:00Z</published><updated>2011-10-22T12:42:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221364.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221364.html"/><content type="html">&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;WCF支持多种序列化方式，决定使用何种取决于多种因素，包括是否希望共享类型或契约，是否支持现有.net类型，是否保留引用等等。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;&lt;strong&gt;DataContractSerializer&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;WCF中的默认序列化方式，其目的是对基于XSD schema契约进行共享，将CLR类型映射成XSD中定义的类型，XSD是应用程序间数据交换的协议。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;如：使用XSD在 .NET与Java应用程序之间交换数据，以字符串为例：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110222010088771.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="XSD类型" border="0" alt="XSD类型" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110222010102873.png" width="644" height="158" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;DataContractSerializer Demo：展示&lt;/span&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;如何使用DataContract，并获取实体类的Schema信息，使用DataContractSerializer序列化输出&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;实体类：&lt;/span&gt;&lt;/p&gt;    [DataContract]&lt;br/&gt;    public class Employee&lt;br/&gt;    {&lt;br/&gt;        [DataMember]&lt;br/&gt;        public int EmployeeID { get; set; }&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        public string FirstName { get; set; }&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        public string LastName { get; set; }&lt;br/&gt;    }&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;获取Schema：&lt;/span&gt;&lt;/p&gt;public static void WriteSchema(Type type)&lt;br/&gt;        {&lt;br/&gt;            XsdDataContractExporter exporter = new XsdDataContractExporter();&lt;br/&gt;            exporter.Options = new ExportOptions();&lt;br/&gt;            exporter.Export(type);&lt;br/&gt;&lt;br/&gt;            using (FileStream fs = new FileStream(string.Format("{0}/{1}.xsd", AppDomain.CurrentDomain.BaseDirectory, type.Name), FileMode.Create))&lt;br/&gt;            {&lt;br/&gt;                foreach (XmlSchema schema in exporter.Schemas.Schemas())&lt;br/&gt;                {&lt;br/&gt;                    schema.Write(fs);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;序列化输出：&lt;/span&gt;&lt;/p&gt;public static void Serialize(object obj)&lt;br/&gt;        {&lt;br/&gt;            using (FileStream fs = new FileStream(string.Format("{0}/{1}.xml", AppDomain.CurrentDomain.BaseDirectory, obj.GetType().Name), FileMode.Create))&lt;br/&gt;            {&lt;br/&gt;                DataContractSerializer serializer = new DataContractSerializer(obj.GetType());&lt;br/&gt;                serializer.WriteObject(fs, obj);&lt;br/&gt;            }&lt;br/&gt;        }&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;Schema 数据：&lt;/span&gt;&lt;/p&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br/&gt;&amp;lt;xs:schema xmlns:tns="http://schemas.datacontract.org/2004/07/JerryShi.EssentialWCF" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/JerryShi.EssentialWCF" xmlns:xs="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;br/&gt;  &amp;lt;xs:complexType name="Employee"&amp;gt;&lt;br/&gt;    &amp;lt;xs:sequence&amp;gt;&lt;br/&gt;      &amp;lt;xs:element minOccurs="0" name="EmployeeID" type="xs:int" /&amp;gt;&lt;br/&gt;      &amp;lt;xs:element minOccurs="0" name="FirstName" nillable="true" type="xs:string" /&amp;gt;&lt;br/&gt;      &amp;lt;xs:element minOccurs="0" name="LastName" nillable="true" type="xs:string" /&amp;gt;&lt;br/&gt;    &amp;lt;/xs:sequence&amp;gt;&lt;br/&gt;  &amp;lt;/xs:complexType&amp;gt;&lt;br/&gt;  &amp;lt;xs:element name="Employee" nillable="true" type="tns:Employee" /&amp;gt;&lt;br/&gt;&amp;lt;/xs:schema&amp;gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;序列化数据：&lt;/span&gt;&lt;/p&gt;&amp;lt;Employee xmlns="http://schemas.datacontract.org/2004/07/JerryShi.EssentialWCF" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br/&gt;  &amp;lt;EmployeeID&amp;gt;1&amp;lt;/EmployeeID&amp;gt;&lt;br/&gt;  &amp;lt;FirstName&amp;gt;Jerry&amp;lt;/FirstName&amp;gt;&lt;br/&gt;  &amp;lt;LastName&amp;gt;Shi&amp;lt;/LastName&amp;gt;&lt;br/&gt;&amp;lt;/Employee&amp;gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;&lt;strong&gt;NetDataContractSerializer&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;共享类型的序列化机制，如果在客户端与服务器之间，类型完全一致，则可以使用此序列化。 NetDatacontractSerializer 在序列化中保留了CLR类型和引用信息，支持类型不变性(type fidelity)。 除此之外NetDataContractSerializer 与 DataContractSerializer 没有区别。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;对类型信息的共享，违背了只共享契约的原则，因此NetDataContractSerializer不适用于跨应用的系统，而适用于单一应用程序内部开发。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;序列化代码：&lt;/span&gt;&lt;/p&gt;public static void NetDataContractSerialize(object obj)&lt;br/&gt;        {&lt;br/&gt;            using (FileStream fs = new FileStream(string.Format("{0}/{1}_NetDataContractSerialize.xml", AppDomain.CurrentDomain.BaseDirectory, obj.GetType().Name), FileMode.Create))&lt;br/&gt;            {&lt;br/&gt;                NetDataContractSerializer serializer = new NetDataContractSerializer();&lt;br/&gt;                serializer.WriteObject(fs, obj);&lt;br/&gt;            }&lt;br/&gt;        }&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;序列化数据：&lt;/span&gt;&lt;/p&gt;&amp;lt;Employee z:Id="1" z:Type="JerryShi.EssentialWCF.Employee" z:Assembly="JerryShi.EssentialWCF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://schemas.datacontract.org/2004/07/JerryShi.EssentialWCF" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"&amp;gt;&lt;br/&gt;  &amp;lt;EmployeeID&amp;gt;1&amp;lt;/EmployeeID&amp;gt;&lt;br/&gt;  &amp;lt;FirstName z:Id="2"&amp;gt;Jerry&amp;lt;/FirstName&amp;gt;&lt;br/&gt;  &amp;lt;LastName z:Id="3"&amp;gt;Shi&amp;lt;/LastName&amp;gt;&lt;br/&gt;&amp;lt;/Employee&amp;gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;NetDataContractSerializer 与 DataContractSerializer 比较：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;1. 以自定义格式表示对象信息；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;2. 包含对象Assmebly信息；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;&lt;strong&gt;XmlSerializer&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;从.Net2.0起出现，支持现有.Net 类型，与ASP.NET Web Service兼容，能够控制XML输出结果&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;优势：&amp;nbsp; 向前兼容、对序列化后的XML可以进行控制；。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;使用XmlSerializer的三种方式：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;1. 默认序列化方式，要求 构造方法必须为public，所有的public类型的字段及读写属性均会进行序列化；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;2. 使用XmlElement和XmlAttribute特性，对public字段及读写属性进行标记，可以控制public字段和属性在xml中如何表示；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;3. 使用IXmlSerializable接口来定制XmlSerializer的序列化，这种方法允许对序列化过程彻底的定制；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;序列化数据：&lt;/span&gt;&lt;/p&gt;&amp;lt;Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&amp;gt;&lt;br/&gt;  &amp;lt;EmployeeID&amp;gt;1&amp;lt;/EmployeeID&amp;gt;&lt;br/&gt;  &amp;lt;FirstName&amp;gt;Jerry&amp;lt;/FirstName&amp;gt;&lt;br/&gt;  &amp;lt;LastName&amp;gt;Shi&amp;lt;/LastName&amp;gt;&lt;br/&gt;&amp;lt;/Employee&amp;gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;结果比较：与DataContractSerializer的结果很相似，最大的差异：XmlSerializer没有DataContractSerializer支持的类型多，但对Xml序列化数据有更多的控制能力。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;特性：XmlSerializerFormat 可以用在服务契约、操作契约或服务上，用来指定WCF使用XmlSerializer 序列化方式。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;在WCF契约中使用XmlSerializer 的方式，除了使用XmlSerializerFormat以外，也可以在使用svcutil.exe时使用参数： /serializer:xmlserializer 来生成以来XmlSerializer的代理代码。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;DataContractJsonSerializer&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;从 .Net Framework 3.5 中出现，支持JavaScript对象序列化后的格式，适用于 Ajax、Silverlight 等应用。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;当使用WebScriptEnablingBehavior行为 或 当WebHttpBehavior行为被配置成使用Json编码时，就会使用DataContractJsonSerializer。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;DataContractJsonSerializer 遵循与DataContractSerializer一样的序列化规则，只是输出的格式是Json而不是Xml。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;序列化数据：&lt;/span&gt;&lt;/p&gt;{"EmployeeID":1,"FirstName":"Jerry","LastName":"Shi"}&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;选择序列化器&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;1. 如果需要支持现有类型或DataContractSerializer所不支持的序列化方式，应考虑XmlSerializer；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;2. WCF 对NetDataContractSerializer没有直接支持，必须编写代码完成，不提倡使用；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span face="微软雅黑" style="font-family: 微软雅黑;"&gt;3. DataContractJsonSerializer 主要用于Web 应用，Ajax或Silverlight&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2221364.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221364.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221064.html</id><title type="text">序列化 VS 编码</title><summary type="text">DataContract序列化机制，将CLR类型转换成符合标准的XML，在客户端与服务之间进行传输。然而有许多情况下DataContract序列化机制不足以完成工作。 WCF并没有遵循序列化的标准定...</summary><published>2011-10-22T03:45:00Z</published><updated>2011-10-22T03:45:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221064.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221064.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;DataContract序列化机制，将CLR类型转换成符合标准的XML，在客户端与服务之间进行传输。然而有许多情况下DataContract序列化机制不足以完成工作。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;WCF并没有遵循序列化的标准定义，而是将序列化定义为将对乡土转化为XML信息集（XML Infoset） 的过程。XML Infoset 是一个数据模型，WCF用它在内部表示一个消息。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;System.ServiceModel.Chnnels.Message是代表XML Infoset的类。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt; XML Infoset 是用来表示XML文档的数据类型，也是XML的基本抽象定义。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;XML与XML Infoset之间的关键区别：XML Infoset未指定一种特定的格式，所以，尽管XML标准使用的是文本格式，XML Infoset却没有任何限制。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;XML Infoset 与 XML相比的优势：只要消息是基于XML Infoset的，WCF就可以用不同的格式来表示它，其中包括了XML1.1规范制定的文本格式，也可以是其他格式如二进制。也可以使用XML，同时可以根据互通性和性能要求选择合适的消息格式。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110221144398557.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="XML Infoset" border="0" alt="XML Infoset" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110221144396954.png" width="244" height="210" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;编码描述将WCF消息转化成字节数组的过程，这样消息才能通过传输协议进行发送。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;WCF提供5种编码方式：二进制、文本、消息传输优化机制（MTOM）、JSON、XML。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;如果想在.NET 应用程序之间获得最佳性能，应选用BiaryMessageEncoder；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;如果要基于WS-*的Web Service, 则应选用TextMessageEncoder和MtomMessageEncoder；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;如果要基于Ajax应用通信，则应选用JsonMessageEncoder；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;如果已有的编码器不能满足要求，则可以扩展WCF来支持新的编码器；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2221064.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/22/2221064.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/10/21/2215965.html</id><title type="text">自定义 Behavior</title><summary type="text">自定义Behavior 允许在WCF 构建运行时环境和消息处理管道的关键点上插入代码。</summary><published>2011-10-21T14:31:00Z</published><updated>2011-10-21T14:31:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/10/21/2215965.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/10/21/2215965.html"/><content type="html">&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;自定义Behavior 允许在WCF 构建运行时环境和消息处理管道的关键点上插入代码。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;实现自定义行为的步骤：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;1. 创建一个实现了 Inspector、Selector、Formatter、或Invoker 接口的类；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;2. 创建一个实现了下列行为接口之一的类：IServiceBehavior、IEndpointBehavior、IOperationBehavior或IContractBehavior；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;3. 配置客户端或服务来使用行为，可由 代码、配置文件、属性来完成；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;strong&gt;服务端行为实现消息检验器&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;该Demo实现一个日志行为，输出端点发送和接收的每条消息，代码实现了从端点行为调用的一个消息检验器，以及在一个自定义扩管服务中手工的向服务描述添加端点行为。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class MyEndpointBehavior : IEndpointBehavior&lt;br/&gt;    {&lt;br/&gt;        #region IEndpointBehavior Members&lt;br/&gt;&lt;br/&gt;        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)&lt;br/&gt;        {&lt;br/&gt;            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyMessageInspector());&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void Validate(ServiceEndpoint endpoint)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public class MyMessageInspector : IDispatchMessageInspector&lt;br/&gt;    {&lt;br/&gt;&lt;br/&gt;        #region IDispatchMessageInspector Members&lt;br/&gt;&lt;br/&gt;        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)&lt;br/&gt;        {&lt;br/&gt;            Console.WriteLine(request.ToString());&lt;br/&gt;            return request;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void BeforeSendReply(ref Message reply, object correlationState)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;/div&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;执行结果：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/20111017231605437.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="结果" border="0" alt="结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110172316069466.png" width="533" height="484" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;结果分析：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;服务端输出每次接收到的Message数据；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;strong&gt;通过属性暴露服务操作行为的参数检验器&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;Demo功能说明： 使用正则表达式对参数进行校验，当参数无效时返回错误消息； 从操作行为调用参数检验器，实现属性的操作行为，在服务定义中通过属性引用将操作行为添加到服务描述中；&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;[AttributeUsage(AttributeTargets.Method)]&lt;br/&gt;    public class MyOperationBehavior : Attribute, IOperationBehavior&lt;br/&gt;    {&lt;br/&gt;        public string Pattern;&lt;br/&gt;        public string Message;&lt;br/&gt;&lt;br/&gt;        #region IOperationBehavior Members&lt;br/&gt;&lt;br/&gt;        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)&lt;br/&gt;        {&lt;br/&gt;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)&lt;br/&gt;        {&lt;br/&gt;            dispatchOperation.ParameterInspectors.Add(new MyParameterInspector(Pattern, Message));&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void Validate(OperationDescription operationDescription)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    public class MyParameterInspector : IParameterInspector&lt;br/&gt;    {&lt;br/&gt;        string pattern;&lt;br/&gt;        string message;&lt;br/&gt;&lt;br/&gt;        public MyParameterInspector(string pattern, string message)&lt;br/&gt;        {&lt;br/&gt;            this.pattern = pattern;&lt;br/&gt;            this.message = message;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #region IParameterInspector Members&lt;br/&gt;&lt;br/&gt;        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)&lt;br/&gt;        {&lt;br/&gt;            &lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public object BeforeCall(string operationName, object[] inputs)&lt;br/&gt;        {&lt;br/&gt;            foreach (object input in inputs)&lt;br/&gt;            {&lt;br/&gt;                if (input != null &amp;amp;&amp;amp; input.GetType().Equals(typeof(string)))&lt;br/&gt;                {&lt;br/&gt;                    Regex regex = new Regex(pattern);&lt;br/&gt;                    if (regex.IsMatch(input.ToString()))&lt;br/&gt;                    {&lt;br/&gt;                        throw new FaultException(string.Format("Parameter out of range : {0} , {1}", input.ToString(), message));&lt;br/&gt;                    }&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;            return null;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;br/&gt;    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]&lt;br/&gt;    public class StockService : IStockService&lt;br/&gt;    {        &lt;br/&gt;        public StockService()&lt;br/&gt;        {&lt;br/&gt;            Console.WriteLine("{0}:Created new instance of StockService on thread", DateTime.Now);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public class Worker&lt;br/&gt;        {&lt;br/&gt;            public string ticker;&lt;br/&gt;            public Update workProcess;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public static Hashtable workers = new Hashtable();&lt;br/&gt;        public static object locker = new object();&lt;br/&gt;        private int callsCounter = 0;&lt;br/&gt;&lt;br/&gt;        #region IStockService Members&lt;br/&gt;&lt;br/&gt;        [MyOperationBehavior(Pattern="[^a-zA-Z]",Message="Only alpha characters allowed")]&lt;br/&gt;        public double GetPrice(string ticker)&lt;br/&gt;        {&lt;br/&gt;            Console.WriteLine("{0}: GetPrice called on thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);            &lt;br/&gt;            Thread.Sleep(5000);&lt;br/&gt;            return 94.85;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        public void RegisterForUpdate(string ticker)&lt;br/&gt;        {&lt;br/&gt;            Worker worker = null;&lt;br/&gt;&lt;br/&gt;            if (!workers.ContainsKey(ticker))&lt;br/&gt;            {&lt;br/&gt;                worker = new Worker();&lt;br/&gt;                worker.ticker = ticker;&lt;br/&gt;                worker.workProcess = new Update();&lt;br/&gt;                worker.workProcess.ticker = ticker;&lt;br/&gt;                workers.Add(ticker, worker);&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            worker = (Worker)workers[ticker];&lt;br/&gt;            IStockServiceCallback c = OperationContext.Current.GetCallbackChannel&lt;istockservicecallback&gt;(); lock (worker.workProcess.callbacks) { worker.workProcess.callbacks.Add(c); } Thread t = new Thread(new ThreadStart(worker.workProcess.SendUpdateToClient)); t.IsBackground = true; t.Start(); } public StockPrice GetStockPrice(string ticker) { StockPrice p = new StockPrice(); Console.WriteLine("{0}: GetPrice called on thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId); p.Price = 94.85; lock (locker) { p.CallsCounter = ++callsCounter; } Thread.Sleep(1000); return p; } #endregion } public class Update { public string ticker; public List&lt;istockservicecallback&gt; callbacks = new List&lt;istockservicecallback&gt;(); public void SendUpdateToClient() { Random w = new Random(); Random p = new Random(); for (int i = 0; i &amp;lt; 10; i++) { Thread.Sleep(w.Next(5000)); lock (callbacks) { foreach (IStockServiceCallback callback in callbacks) { try { callback.PriceUpdate("msft", 100.00 + p.NextDouble()); } catch (Exception ex) { Console.WriteLine("Error sending cache to client:{0}", ex.Message); } } } } } }&lt;/istockservicecallback&gt;&lt;/istockservicecallback&gt;&lt;/istockservicecallback&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;执行结果&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;调试状态下直接报出错误信息&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;strong&gt;通过配置文件暴露服务行为&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;实现IServiceBehavior，代码：&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class MyServiceBehavior : IServiceBehavior&lt;br/&gt;    {&lt;br/&gt;        string evaluationKey;&lt;br/&gt;        string evaluationType;&lt;br/&gt;&lt;br/&gt;        public MyServiceBehavior(string evaluationKey, string evaluationType)&lt;br/&gt;        {&lt;br/&gt;            this.evaluationKey = evaluationKey;&lt;br/&gt;            this.evaluationType = evaluationType;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #region IServiceBehavior Members&lt;br/&gt;&lt;br/&gt;        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection&lt;serviceendpoint&gt; endpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { if (evaluationType.Equals("Enterprise", StringComparison.OrdinalIgnoreCase) &amp;amp; !evaluationKey.Equals("SuperSecretEvaluationKey", StringComparison.OrdinalIgnoreCase)) { throw new Exception(string.Format("Invalid evaluation key. Type:{0}", evaluationType)); } } #endregion }&lt;/serviceendpoint&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;配置：&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;system.servicemodel&gt; &lt;servicehostingenvironment multiplesitebindingsenabled="true"&gt;&lt;/servicehostingenvironment&gt; &lt;extensions&gt; &lt;behaviorextensions&gt; &lt;add name="FreeTrial" type="JerryShi.EssentialWCF.MyBehaviorExtensionElement, JerryShi.EssentialWCF"&gt;&lt;/add&gt; &lt;/behaviorextensions&gt; &lt;/extensions&gt; &lt;services&gt; &lt;service name="JerryShi.EssentialWCF.StockService" behaviorconfiguration="StockServiceBehavior_CustomerAuth"&gt; &lt;host&gt; &lt;baseaddresses&gt; &lt;add baseaddress="net.tcp://localhost:809/StockService"&gt; &lt;/add&gt;&lt;/baseaddresses&gt; &lt;/host&gt; &lt;endpoint address="" binding="netTcpBinding" contract="JerryShi.EssentialWCF.IStockService"&gt;&lt;/endpoint&gt; &lt;endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"&gt;&lt;/endpoint&gt; &lt;/service&gt; &lt;/services&gt; &lt;bindings&gt; &lt;nettcpbinding&gt; &lt;binding name="BankService_netTcpBinding" transactionflow="true"&gt;&lt;/binding&gt; &lt;/nettcpbinding&gt; &lt;/bindings&gt; &lt;behaviors&gt; &lt;behavior name="StockServiceBehavior_CustomerAuth"&gt; &lt;freetrial evaluationkey="SuperSecretEvaluationKey" evaluationtype="Enterprise"&gt;&lt;/freetrial&gt; &lt;/behavior&gt; &lt;/behaviors&gt; &lt;/system.servicemodel&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2215965.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/21/2215965.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/10/17/2194840.html</id><title type="text">操作行为 之 事务</title><summary type="text">短期事务：简单业务处理，时间段，几秒内完成，外部以来很少</summary><published>2011-10-17T13:53:00Z</published><updated>2011-10-17T13:53:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/10/17/2194840.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/10/17/2194840.html"/><content type="html">&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;事务场景：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;1. 长期事务：多步骤业务处理，时间跨度长，如几分钟、几天、上月，涉及多个组织或工作流；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;2. 短期事务：简单业务处理，时间段，几秒内完成，外部以来很少； &lt;/span&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;短期事务ACID特性 ：原子性、一致性、隔离性、持久性&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;WCF支持短期事务，利用两种架构来实现：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;1. .Net Framewok 和 Windows Infrastructure 支持 Microsoft环境中运行的事务；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;2. 利用跨平台的WS-* 标准。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;strong&gt;事务化操作&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;声明操作行为： [OperationBehavior(TransactionScopeRequired=true)]，表示将服务操作标识为事务化操作。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;操作说明：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;1. WCF在将控制权转换为服务方法前创建一个新事务；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;2. 将执行线程纳入第一步创建的事务中；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;可以显式或隐式的指定当操作完成时的提交事务的操作。 声明操作行为：[OperationBehavior(TransactionAutoComplete=true)]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;TransactionAutoCompleted=true 表示若没有抛出任何错误，操作会隐式的认定执行完成；若抛出错误，操作会认定为未完成，针对事务资源的部分更新会被回滚。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;TransactionAutoCompleted=false 表示必须在方法返回前显示的调用 OperationContext.Current.SetTransactionCompleted() ，若使用了显式方法，则必须在通信信道中使用基于会话的绑定，并使用[ServiceContract(SessionMode=SessionMode.Allowed)]使用服务契约支持会话。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;代码示例：BankService 实现两个方法，GetBalance 不需要事务，Transfer 指定了事务，并隐式提交事务。通过输出事务的 LocalIdentifier和DistributedIdentifier来判断事务执行情况&lt;/span&gt;&lt;/p&gt;    public class BankService: IBankService&lt;br/&gt;    {&lt;br/&gt;        #region IBankService Members&lt;br/&gt;&lt;br/&gt;        [OperationBehavior(TransactionScopeRequired = false)]&lt;br/&gt;        public double GetBalance(string AccountName)&lt;br/&gt;        {&lt;br/&gt;            DBAccess dbAccess = new DBAccess();&lt;br/&gt;            double amount = dbAccess.GetBalance(AccountName);&lt;br/&gt;            dbAccess.Audit(AccountName, "Query", amount);&lt;br/&gt;            return amount;&lt;br/&gt;        }&lt;br/&gt;        &lt;br/&gt;        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]&lt;br/&gt;        public void Transfer(string From, string To, double amount)&lt;br/&gt;        {&lt;br/&gt;            try&lt;br/&gt;            {&lt;br/&gt;                Withdraw(From, amount);&lt;br/&gt;                Deposit(To, amount);&lt;br/&gt;            }&lt;br/&gt;            catch (Exception ex)&lt;br/&gt;            {&lt;br/&gt;                throw ex;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;&lt;br/&gt;        private void Withdraw(string accountName, double amount)&lt;br/&gt;        {&lt;br/&gt;            DBAccess dbAccess = new DBAccess();&lt;br/&gt;            dbAccess.Withdraw(accountName, amount);&lt;br/&gt;            dbAccess.Audit(accountName, "Withdraw", amount);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        private void Deposit(string accountName, double amount)&lt;br/&gt;        {&lt;br/&gt;            DBAccess dbAccess = new DBAccess();&lt;br/&gt;            dbAccess.Deposit(accountName, amount);&lt;br/&gt;            dbAccess.Audit(accountName, "Deposit", amount);&lt;br/&gt;        }&lt;br/&gt;    }&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;执行结果：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;在执行过程中若本机没有打开MSDTC服务，则会出现错误，必须要进行配置。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110051010466358.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="MSDTC" border="0" alt="MSDTC" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110051010473260.png" width="443" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110051010479639.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="分布式事务" border="0" alt="分布式事务" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110051010496093.png" width="511" height="484" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;结果分析：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;1. Withdraw 执行中打开第一个数据库连接，当前存在一个上下文事务，并且属于本地事务；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;2. Deposit 执行中打开第二个数据库连接，导致事务从本地事务升级到分布式事务；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;导致事务升级的代码：&lt;/span&gt;&lt;/p&gt; private void Withdraw(string accountName, double amount)&lt;br/&gt;        {&lt;br/&gt;            DBAccess dbAccess = new DBAccess();//创建SqlConnection&lt;br/&gt;            dbAccess.Withdraw(accountName, amount);&lt;br/&gt;            dbAccess.Audit(accountName, "Withdraw", amount);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        private void Deposit(string accountName, double amount)&lt;br/&gt;        {&lt;br/&gt;            DBAccess dbAccess = new DBAccess();//创建SqlConnection&lt;br/&gt;            dbAccess.Deposit(accountName, amount);&lt;br/&gt;            dbAccess.Audit(accountName, "Deposit", amount);&lt;br/&gt;        }&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;由于创建两个SqlConnection实例，导致分布式事务出现，可以对此进行优化，将dbAccess 实例作为全局变量，共用同一个SqlConnection实例。优化后结果如下：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/201110051010494424.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="本地事务" border="0" alt="本地事务" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201110/20111005101051355.png" width="520" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;&lt;strong&gt;操作之间的事务流转&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;背景：跨越服务边界的事务，如：用户下订单需要同时调用订单服务及客户信息服务，增加订单的同时增加客户信息。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;在WCF中，服务边界之间的事务流转信息统称为事务流（transaction flow），要在服务边界之间定义事务流，需要以下5个操作：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;1. （服务契约）SessionMode.Required，服务契约必须使用Session，只有这样客户端才能在参与事务的各个服务之间共享信息；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;2. （操作行为）TransactionScopeRequired=true，操作行为必须在事务上下文内，若不存在上下文，则创建一个新事物；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;3. （操作契约）TransactionFlowOption.Allowed，操作契约必须允许消息头中包含用于流转的事务信息；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;4. （绑定）TransactionFlow=true，允许事务跨越多个服务调用， 绑定必须激活事务流，使得信道能在SOAP头中放置事务信息，绑定必须支持会话；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;5. （客户端）TransactionScope，初始化事务的角色（通常是客户端）必须在调用服务操作时使用一个事务作用域，必须调用TransactionScope.Close()来提交修改； &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 微软雅黑;" face="微软雅黑"&gt;暂无Demo&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2194840.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/10/17/2194840.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/09/28/2194818.html</id><title type="text">服务行为 之 元数据</title><summary type="text">元数据：将服务的ABC（地址、绑定、契约）以 服务提供者与服务消费者共同认可的XML 描述的形式描述出来。 要使元数据对客户端可用，需要两个步骤： 1. 按某种可读的格式导出元数据； 2. 发布...</summary><published>2011-09-28T13:38:00Z</published><updated>2011-09-28T13:38:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/09/28/2194818.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/09/28/2194818.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;元数据：将服务的ABC（地址、绑定、契约）以 服务提供者与服务消费者共同认可的XML 描述的形式描述出来。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;要使元数据对客户端可用，需要两个步骤：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;1. 按某种可读的格式导出元数据；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;2. 发布到一个可用的位置；&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font face="微软雅黑"&gt;默认的导出格式是WSDL，WCF使用WS-MetadataExchange协议发布元数据，或者将元数据发布为HTTP GET的&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="微软雅黑"&gt;Response。导出与发布的操作都由 ServiceMetadataBehavior 实现&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;服务通过Mex端点交换数据，Mex端点类似于我们开发的端点，同样有自己的 ABC，同样可以通过配置文件进行添加。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;Mex端点的ABC及示例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;契约： System.ServiceModel.Description.IMetadataExchange 接口，其服务实现了检查服务并以WSDL格式提供和发布元数据的方法；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;绑定： CLR提供的绑定：mexHttpBinding、mexHttpsBinding、mexNamedPipeBinding、mexTcpBinding；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;地址： 地址可以是相对地址，也可以是绝对地址，通常配置文件中相对地址为mex&lt;/font&gt;&lt;/p&gt;  &lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;   &lt;service behaviorconfiguration="StockServiceBehavior" name="JerryShi.EssentialWCF.StockService"&gt;&lt;br/&gt;        &lt;host&gt;&lt;br/&gt;          &lt;baseaddresses&gt;&lt;br/&gt;            &lt;add baseaddress="net.tcp://localhost:809/StockService" /&gt;&lt;br/&gt;          &lt;/baseaddresses&gt;&lt;br/&gt;        &lt;/host&gt;&lt;br/&gt;        &lt;endpoint contract="JerryShi.EssentialWCF.IStockService" binding="netTcpBinding" address="" /&gt;&lt;br/&gt;        &lt;endpoint contract="IMetadataExchange" binding="mexTcpBinding" address="mex" /&gt;&lt;br/&gt;      &lt;/service&gt;&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;Mex端点自托管代码&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  using (ServiceHost servcieHost = new ServiceHost(typeof(StockService), new Uri(url)))&lt;br/&gt;            {&lt;br/&gt;                servcieHost.AddServiceEndpoint(typeof(IStockService), binding, &amp;quot;&amp;quot;);&lt;br/&gt;&lt;br/&gt;                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();&lt;br/&gt;                behavior.HttpGetEnabled = true;&lt;br/&gt;                servcieHost.Description.Behaviors.Add(behavior);&lt;br/&gt;                servcieHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), &amp;quot;mex&amp;quot;);&lt;br/&gt;&lt;br/&gt;                servcieHost.Open();&lt;br/&gt;&lt;br/&gt;                Console.WriteLine(&amp;quot;Press &lt;enter&gt; to terminate service...&amp;quot;);&lt;br/&gt;                Console.ReadLine();&lt;br/&gt;                servcieHost.Close();&lt;br/&gt;            }&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2194818.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/09/28/2194818.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/jerryshi/archive/2011/09/27/2192288.html</id><title type="text">服务行为 之 并发与实例化</title><summary type="text">服务行为中的 并发与实例化行为</summary><published>2011-09-27T14:26:00Z</published><updated>2011-09-27T14:26:00Z</updated><author><name>JerryShi</name><uri>http://www.cnblogs.com/jerryshi/</uri></author><link rel="alternate" href="http://www.cnblogs.com/jerryshi/archive/2011/09/27/2192288.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/jerryshi/archive/2011/09/27/2192288.html"/><content type="html">&lt;p&gt;&lt;font face="微软雅黑"&gt;本章节介绍 服务行为中的 并发与实例化行为，服务行为的介绍可以参考 《&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/09/25/2190009.html" target="_blank"&gt; WCF Behaviors（行为）&lt;/a&gt;》 &lt;/font&gt;&lt;/p&gt;  &lt;br /&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;并发与实例化的引入，相关的名词解释&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;并发（Concurrency）：对同时执行的任务数量，度量单位为任务（如请求、作业、事务等）；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;执行时间（Execution Time）：完成任务所用的时间，度量单位为时间（如秒、毫秒等）；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;吞吐量（Throughput）：固定时间内完成的任务数量，度量单位为 任务/时间 如：请求/秒、事务/分钟；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;提高吞吐量的办法： &lt;/font&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font face="微软雅黑"&gt;减少执行时间&lt;/font&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 通过修改任务内部算法或增加硬件资源来完成，WCF在此方面作用有限。&lt;/font&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font face="微软雅黑"&gt;提高并发&lt;/font&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 通过提高单位时间内的并发数量， WCF中控制另发的两个行为：&lt;em&gt;&lt;font color="#ff0000"&gt;InstanceContextMode&lt;/font&gt;&lt;/em&gt; 和 &lt;em&gt;&lt;font color="#ff0000"&gt;ConcurrencyMode &lt;/font&gt;&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;ServiceBehavior 属性不定义在接口上，而是服务类上，因为ServiceBehavior属性针对的是服务的行为，而不是服务的契约。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;InstanceContextMode 服务行为用于控制实例化，取值说明：&lt;/font&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;font face="微软雅黑"&gt;Single ： 所有入站请求均共用同一个服务类的实例；&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font face="微软雅黑"&gt;PerCall ：为每一个入站请求创建一个服务类的实例；&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font face="微软雅黑"&gt;PerSession：为每一个会话创建一个服务类的实例，默认值；&lt;/font&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;InstanceContextMode 的默认值为PerSession，但当使用无会话的信道（通道）或者无会话绑定时，会变化为PerCall行为。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;ConcurrencyMode 服务行为用于控制服务实例内的线程并发，取值说明：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;Single：同一时刻仅能有一个线程访问服务类，默认值；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;Reentrant：同一个是仅能有一个线程访问服务类，但该线程可以暂时离开服务类进入等待状态，而后又激活继续访问；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;Multiple：多线程并发访问服务类。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;Single 是最安全的设置，服务操作不需要担心线程安全问题，Multiple 需要类具有内置的线程安全能力。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;同时使用 InstanceContextMode 与 ConcurrencyMode 这两个设置，可以配置服务的实例化和并发来满足特定的性能需求。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;会话实例 - 单线程 - 默认-示例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;定义服务接口&lt;/font&gt;&lt;/p&gt;  &lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;   [ServiceContract]&lt;br/&gt;    public interface IStockService&lt;br/&gt;    {        &lt;br/&gt;        [OperationContract]&lt;br/&gt;        double GetPrice(string ticker);&lt;br/&gt;    }&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;实现服务，输出线程ID&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  public class StockService : IStockService&lt;br/&gt;    {&lt;br/&gt;        public StockService()&lt;br/&gt;        {&lt;br/&gt;            Console.WriteLine(&amp;quot;{0}:Created new instance of StockService on thread&amp;quot;, DateTime.Now);&lt;br/&gt;        }&lt;br/&gt;      &lt;br/&gt;        #region IStockService Members&lt;br/&gt;&lt;br/&gt;        public double GetPrice(string ticker)&lt;br/&gt;        {&lt;br/&gt;            Console.WriteLine(&amp;quot;{0}: GetPrice called on thread {1}&amp;quot;, DateTime.Now, Thread.CurrentThread.ManagedThreadId);&lt;br/&gt;&lt;br/&gt;            return 94.95;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        #endregion&lt;br/&gt;    }&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;客户端异步调用代码&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  public static void GetPriceWithAsync(string address, Binding binding)&lt;br/&gt;        {&lt;br/&gt;            //IStockService proxy = CreateStockServiceProxy(address, binding);&lt;br/&gt;            StockServiceClient proxy = new StockServiceClient(stockContext, binding, new EndpointAddress(address));&lt;br/&gt;&lt;br/&gt;            IAsyncResult arGetPrice;&lt;br/&gt;            for (int i = 0; i &amp;lt; 3; i++)&lt;br/&gt;            {&lt;br/&gt;                Console.WriteLine(&amp;quot;{0} : Calling GetPrice&amp;quot;, DateTime.Now);&lt;br/&gt;                arGetPrice = proxy.BeginGetPrice(&amp;quot;msft&amp;quot;, GetPriceCallback, proxy);&lt;br/&gt;                Thread.Sleep(100);//为了让输出更清晰&lt;br/&gt;                Interlocked.Increment(ref c);&lt;br/&gt;            }&lt;br/&gt;            while (c &amp;gt; 0)&lt;br/&gt;            {&lt;br/&gt;                Thread.Sleep(1000);&lt;br/&gt;            }&lt;br/&gt;            stockProxy.Close();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        static void GetPriceCallback(IAsyncResult ar)&lt;br/&gt;        {&lt;br/&gt;            double price = ((StockServiceClient)ar.AsyncState).EndGetPrice(ar);&lt;br/&gt;            Console.WriteLine(&amp;quot;{0}: GetPrice result:{1}&amp;quot;, DateTime.Now, price);&lt;br/&gt;            Interlocked.Decrement(ref c);&lt;br/&gt;        }&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;执行结果&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262121511068.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="默认并发-实例化-无会话结果" border="0" alt="默认并发-实例化-无会话结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262121527348.png" width="592" height="484" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;结果分析：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;1. 对每个客户端的请求，服务端仅生成了一个服务实例&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;2. 每个请求都在各自的线程中被执行。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;以上代码采用net.tcp方式进行绑定，net.tcp支持会话，因此InstanceContextMode取值为PerSession；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;ConcurrencyMode.Single 设置使得每个WCF对于每个服务实例只允许一个线程。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;多实例 - 单线程 - 示例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;服务类代码：&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]&lt;br/&gt;    public class StockService : IStockService&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;执行结果&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262157357296.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="多实例-单线程-结果" border="0" alt="多实例-单线程-结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262157364689.png" width="592" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;结果分析：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;1. 为每个请求创建了一个实例；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;2. 每个请求在各自的线程中处理请求。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;InstanceContextMode.PerSession 在绑定不支持会话的情况下会演变为 InstanceContextMode.PerCall ，故如果采用BasicHttpBinding方式，则无须进行设置。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;单实例-多线程-示例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;适用情况：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;服务初始化代价高昂，如：构造方法需要从数据库中加载大量数据，或者构建一个大的数据结构；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;服务代码中存在锁机制，可以保护线程局部安全，提高伸缩性；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;服务类代码：&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]&lt;br/&gt;    public class StockService : IStockService&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;执行结果：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262157371492.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="单实例-多线程结果" border="0" alt="单实例-多线程结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262157387489.png" width="592" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;结果分析：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;1. 服务端仅创建了一次实例；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;2. 每次请求是在不同的线程中执行的；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;单实例 - 单线程 - 单例模式&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;适用情况：没有锁机制，要求先进先出处理方式，调用者存在共享情况&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;服务端代码：&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]&lt;br/&gt;    public class StockService : IStockService&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;执行结果：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109262241292339.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="单实例-单线程-结果" border="0" alt="单实例-单线程-结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/20110926224129114.png" width="592" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;结果分析：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;1. 与 会话实例 - 单线程 - 示例中不同的是，显式声明 InstanceContextMode = InstanceContextMode.Single 后，一旦host成功，自动会创建服务实例;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;2. 多个请求重用一个线程， &lt;/font&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;ConcurrencyMode.Single 设置使得WCF在同一时刻只允许运行一个服务类的一个实例，并不控制创建线程的总量&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;会话级实例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;要实现基于会话的服务实例，必须要实现两点：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;1. 在契约级打开会话功能：SessionMode ： Allowed|NotAllowed|Requied；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;2. 在服务级设置按会话创建服务实例；&lt;/font&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;虽然会话是在契约级别设置是否允许，但其真正实现是在绑定元素指定的信道，因此服务第一次启动时会校验契约行为与信道的兼容性，如果信道需要会话，而绑定不支持会话(如：basicHttpBinding)，则会抛出异常&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;会话实例 - 多线程 - 示例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;代码：&lt;/font&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;  [DataContract]&lt;br/&gt;    public class StockPrice&lt;br/&gt;    {&lt;br/&gt;        [DataMember]&lt;br/&gt;        public double Price;&lt;br/&gt;&lt;br/&gt;        [DataMember]&lt;br/&gt;        public int CallsCounter;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]&lt;br/&gt;    public class StockService : IStockService&lt;br/&gt;    {        &lt;br/&gt;        public StockService()&lt;br/&gt;        {&lt;br/&gt;            Console.WriteLine(&amp;quot;{0}:Created new instance of StockService on thread&amp;quot;, DateTime.Now);&lt;br/&gt;        }&lt;br/&gt;        &lt;br/&gt;        public StockPrice GetStockPrice(string ticker)&lt;br/&gt;        {&lt;br/&gt;            StockPrice p = new StockPrice();&lt;br/&gt;            Console.WriteLine(&amp;quot;{0}: GetPrice called on thread {1}&amp;quot;, DateTime.Now, Thread.CurrentThread.ManagedThreadId);&lt;br/&gt;            &lt;br/&gt;            p.Price = 94.85;&lt;br/&gt;            lock (locker)&lt;br/&gt;            {&lt;br/&gt;                p.CallsCounter = ++callsCounter;&lt;br/&gt;            }&lt;br/&gt;            Thread.Sleep(1000);&lt;br/&gt;            return p;&lt;br/&gt;        }&lt;br/&gt;    }&lt;/div&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;执行结果：启动两个客户端，同时调用&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109272203173820.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="会话实例-多线程-结果" border="0" alt="会话实例-多线程-结果" src="http://images.cnblogs.com/cnblogs_com/jerryshi/201109/201109272203187658.png" width="533" height="484" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;结果分析：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;1. 创建了两个实例，分别针对两个客户端；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;2. 计数器针对两个客户端是独立的，分别计数；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;3. 服务端处理请求在3个线程中进行，属于多线程。&lt;/font&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;如果将InstanceContextMode改为Single，则计数器将从1增长到6&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font face="微软雅黑"&gt;使用配置 控制 实例、线程&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;通过配置对程序中 的多实例、多线程、会话数进行控制&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;maxConcurrentInstances ： 最大并发实例数，当InstanceContextMode取值为 PerSession或PerCall 时此配置会起作用，Single表示只存在一个实例；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;maxConcurrentCalls：最大并发调用数量，当 ConcurrencyMode 为 Mutiple时起作用；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;maxConcurrentSeesions：最大会话数量，当InstanceContextMode取值为PerSession时起作用，当达到最大数量时，会等待其他会话关闭。&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/jerryshi/aggbug/2192288.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/jerryshi/archive/2011/09/27/2192288.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
