WCF中幾個容易忽略的知識點

來源:互聯網
上載者:User
近來看WCF相關資料 發現之前一些沒太關注或者有些錯誤認識的知識點,有些也貌似不怎麼常用。於是整理了這一則筆記。

1、 WCF中的綁定。

可以通過綁定無參數建構函式執行個體化綁定,然後調用CreateBindingElements擷取到此種綁定的繫結元素。

WSHttpBinding httpBinding = new WSHttpBinding(); 

BindingElementCollection collection = httpBinding.CreateBindingElements();
foreach (var element in collection)
{                      

Console.WriteLine(element.GetType().FullName);
}

 
輸入如下: 

 

如果對WSHttpBinding 更換一下建構函式 ,如:

httpBinding = new WSHttpBinding(SecurityMode.Transport); 

輸出結果如下:

 

如果對綁定指定一些配置,如安全配置,則它的繫結元素可能與調用無參數建構函式執行個體化對象調用CreateBindingElements擷取到的繫結元素不同。也就是說對於同一綁定,使用不同的配置可以更改它的繫結元素類型;不管採用何種配置,對綁定來說傳輸綁定與編碼繫結元素這兩個是必須的。

2、終結點契約配置

配置中的契約contracts不是契約介面的完全限定名,而是ServiceContractAttribute中ConfigurationName指定的名稱。如果沒有ConfigurationName配置,那麼contracts的完全限定名與ConfigurationName指定的名稱相同。

3、 UnHandler處理器

如果在WCF中需要一個能處理所有訊息的方法,而不關心SOAP訊息的Action。那麼操作方法

的參數可以指定為Message。這種服務作業在WCF中被稱為UnHandler處理器。這種情況下,參數應為Message;

傳回值為void或者Message;OperationCOntractAtrribte的Action設定為"*"

4、WCF序列化中Dos攻擊 

WCF使用的序列化器DataContractSerializer在對資料契約進行序列化或者還原序列化時,為了

防止Dos攻擊,在DataContractSerializer中使用MaxItemsInObjectGraph設定了每次序列化得對

象數量。實際使用的時候可以在實現服務契約介面的服務加上ServiceBehavior標籤中進行設定。如:[ServiceBehavior(MaxItemsInObjectGraph = 60)];或者在serviceBehavior的配置中由

dataContractSerializer指定。如:

 

<behavior name="serviceBehavior">                

<dataContractSerializer maxItemsInObjectGraph="1000"/>                    
</behavior>

 

5、泛型資料契約問題。

泛型為OO裡的一種概念,而服務是基於SOA的,它沒有重載等概念。WCF的預設序列化器DataContractSerializer對

泛型資料契約的序列化,產生的XML預設的根節點元素名稱為:類型名+泛型名1+泛型名2+...+雜湊碼。

可以通過指定模板的形式指定DataContractSerializer序列化後的根節點名:{0}{1}...{n}{#}。當然如果能保證資料契約名稱不重複,也可以直接在DataContract中通過Name指定。

6、自訂集合資料契約類型。

自訂集合資料契約:定義類,實現集合介面。如下定義:

    public class TeacherCollection : IEnumerable<Teacher> 

    {
        private readonly IList<Teacher> teachers = new List<Teacher>();

        public TeacherCollection()
        {
        }

        public TeacherCollection(IList<Teacher> _teachers)
        {
            teachers = _teachers;
        }

        public void Add(Teacher teacher)
        {
            teachers.Add(teacher);
        }

        #region IEnumerable<Teacher> 成員

        public IEnumerator<Teacher> GetEnumerator()
        {
            return teachers.GetEnumerator();
        }

        #endregion

        #region IEnumerable 成員

        IEnumerator IEnumerable.GetEnumerator()
        {
            return teachers.GetEnumerator();
        }

        #endregion
    }

 

在定義契約介面時,可以用自訂集合資料契約。它和IList<Teacher>的區別是:IList<Teacher>中Teacher才是資料契約,IList<Teacher>是資料契約的集合,而TeacherCollection是將整個集合對象最為資料契約。在WCF的預設的序列化器對TeacherCollection和IList<Teacher>的序列化的結果是相同的。

自訂集合契約,如果實現IList介面,則可以不需要添加Add,如果實現了IEmurable介面,則需要Add方法,並且需要有無參建構函式。為了簡化Add方法與建構函式可以讓自訂集合契約直接實現List<T>。對於自訂集合契約,WCF可以直接使用CollectionDataContract將其標記,泛型類T無需標記為DataContract。如下:    [CollectionDataContract(Name = "TeacherList", ItemName = "TeacherEntry", Namespace = "cnblogs.com")]
    public class Collection<T> : List<T>
    {
        private readonly IList<Teacher> teachers = new List<Teacher>();
    
    } 

7、資料契約代理。

資料契約代理實現了IDataContractSurrogate。在WCF中,它可被用於WCF預設的序列器

DataContractSerializer中,用於將資料契約類與其他相似類型的轉化。以下實現Contract類型與

資料契約Employee之間的轉化。

 範例程式碼如下:Contract類:    public class Contract
    {
        public string FullName { get; set; }

        public string Sex { get; set; }
    }資料契約Employee:

 

    [DataContract]
    public class Employee
    {
        [DataMember]
        public string FirstName { get; set; }

        [DataMember]
        public string LastName { get; set; }

        [DataMember]
        public string Gender { get; set; }
    }實現IDataContractSurrogate介面:

 

    class ContactSurrogate : IDataContractSurrogate
    {

        #region IDataContractSurrogate 成員

        public object GetCustomDataToExport(Type clrType, Type dataContractType)
        {
            return null;
        }

        public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
        {
            return null;
        }

        public Type GetDataContractType(Type type)
        {
            if (type==typeof(Contract))
            {
                return typeof (Employee);
            }
            return type;
        }

        public object GetDeserializedObject(object obj, Type targetType)
        {
            Employee employee = obj as Employee;
            if (employee==null)
            {
                return obj;
            }
            return new Contract {FullName = employee.FirstName + employee.LastName, Sex = employee.Gender};
        }

        public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
        {
            
        }

        public object GetObjectToSerialize(object obj, Type targetType)
        {
            Contract contract = obj as Contract;
            if (contract == null)
            {
                return obj;
            }
            return new Employee
                       {
                           FirstName = contract.FullName.Split(" ".ToArray(), StringSplitOptions.None)[0],
                           Gender = contract.Sex,
                           LastName = contract.FullName.Split(" ".ToArray(), StringSplitOptions.None)[1]
                       };
        }

        public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
        {
            return null;
        }

        public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
        {
            return typeDeclaration;
        }

        #endregion
    }

 使用ContactSurrogate進行序列化與還原序列化的方法:

 

    public static void Serializer<T>(T instance,string fileName,IDataContractSurrogate dataContractSurrogate)
        {
            DataContractSerializer serializer=new DataContractSerializer(typeof(T),null,Int32.MaxValue,false,false,dataContractSurrogate);
            using(XmlWriter xmlWriter=XmlWriter.Create(fileName))
            {
                serializer.WriteObject(xmlWriter, instance);
            }
            Process.Start(fileName);
        }

            public static T DeSerializer<T>(string fileName,IDataContractSurrogate dataContractSurrogate)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T), new List<Type>(), Int32.MaxValue, false, false, dataContractSurrogate);
            using (XmlReader xmlReader=XmlReader.Create(fileName))
            {
                object obj = serializer.ReadObject(xmlReader);
                return (T) obj;
            }

        }  


現在對資料契約Employee使用Serializer<T>進行序列化,然後將它序列化後的檔案使用

DeSerializer<T>將它還原序列化成還原序列化為Contract對象。

Employee employee = new Employee {FirstName = "yongbo", Gender = "male", LastName = "Tao"};            

ContactSurrogate contactSurrogate = new ContactSurrogate();
        Tools.Serializer(employee, @"C:\DataContractSurrogate.txt", contactSurrogate);

        Contract obj = Tools.DeSerializer<Contract>(@"C:\DataContractSurrogate.txt", contactSurrogate);
        Console.WriteLine(string.Format("{0} 類型為:{1}。FullName is {2},Sex is {3}",obj,obj.GetType().FullName,obj.FullName,obj.Sex));

輸出如下:

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.