传说中的WCF(6):数据协定(b)
我們繼續(xù),上一回我們了解了數(shù)據(jù)協(xié)定的一部分內(nèi)容,今天我們接著來做實驗。好的,實驗之前先說一句:實驗有風(fēng)險,寫代碼須謹(jǐn)慎。
實驗開始!現(xiàn)在,我們定義兩個帶數(shù)據(jù)協(xié)定的類——Student和AddrInfo。
[DataContract]public class Student{[DataMember]public string Name;[DataMember]public string Phone;[DataMember]public AddrInfo Address;} [DataContract]public class AddrInfo{[DataMember]public string Province;[DataMember]public string City;[DataMember]public string DetailAddr;}
這兩個類有一個特征,Student類的Address字段是一個AddrInfo對象,而我們的服務(wù)定義如下:
方法返回的Student對象,那么,我們來測試一下,AddrInfo能不能被成功序列化和反序列化。下面是注冊和啟動服務(wù)的代碼:
static void Main(string[] args){// 服務(wù)器基址Uri baseAddress = new Uri("http://localhost:1378/services");// 聲明服務(wù)器主機(jī)using (ServiceHost host = new ServiceHost(typeof(MyService), baseAddress)){// 添加綁定和終結(jié)點WSHttpBinding binding = new WSHttpBinding();host.AddServiceEndpoint(typeof(IService), binding, "/test");// 添加服務(wù)描述host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });try{// 打開服務(wù)host.Open();Console.WriteLine("服務(wù)已啟動。");}catch (Exception ex){Console.WriteLine(ex.Message);}Console.ReadKey();}}在客戶端生成的代碼中,兩個類都可以正確生成。
客戶端測試代碼如下:
static void Main(string[] args){WS.ServiceClient cli = new WS.ServiceClient();WS.Student stu = cli.GetStudentInfo();string msg = "學(xué)生姓名:{0}\n聯(lián)系電話:{1}\n" +"地址信息:-----------\n" +"省份:{2}\n" +"市區(qū):{3}\n" +"詳細(xì)地址:{4}";Console.WriteLine(msg, stu.Name, stu.Phone, stu.Address.Province, stu.Address.City, stu.Address.DetailAddr);Console.ReadKey();}
其運行結(jié)果如下:
?
?
下面我們繼續(xù)實驗。
每個學(xué)生可能有多個學(xué)科的成績,因此,我們?yōu)閷W(xué)生類再添加一個成績屬性。
[DataContract]public class Student{[DataMember]public string Name;[DataMember]public string Phone;[DataMember]public AddrInfo Address;[DataMember]public object Scores;} public class MyService : IService{public Student GetStudentInfo(){Student stu = new Student();AddrInfo info = new AddrInfo();info.Province = "廣東省";info.City = "佛山市";info.DetailAddr = "火星路-300號";stu.Name = "小陳";stu.Phone = "1388888888";stu.Address = info;Dictionary<string, float> m_scores = new Dictionary<string, float>();m_scores.Add("語文", 97f);m_scores.Add("英語", 64.5f);m_scores.Add("數(shù)學(xué)", 38f);m_scores.Add("歷史", 77.6f);m_scores.Add("地理", 82.3f);stu.Scores = m_scores;return stu;}}
客戶端測試代碼改為:
現(xiàn)在來測試,就會發(fā)生異常,因為我們?yōu)镾tudent類加的成績屬性是object類型,而我們在協(xié)定方法中給它賦的是 Dictionary<string, float>類型,這樣一來,就算可以序列化也不能被反序列化,因為Dictionary<string, float>無法識別。
現(xiàn)在,我們再為Student類添加一個KnownType特性,看它能不能識別。
[DataContract]
[KnownType(typeof(Dictionary<string, float>))]
public class Student
{
。。。。。
}
這時候,再運行一下。
很可惜,還是報錯了,
?
怎么辦呢?不要放棄,我們繼續(xù)把學(xué)生類修改一下。
[DataContract][KnownType("GetKnowTypes")]public class Student{[DataMember]public string Name;[DataMember]public string Phone;[DataMember]public AddrInfo Address;[DataMember]public object Scores;static Type[] GetKnowTypes(){return new Type[] { typeof(Dictionary<string,float>) };}}GetKnowTypes方法是靜態(tài)方法,KnownType的構(gòu)造函數(shù)中傳遞該方法的名字。看看這回調(diào)用能否成功?
堅持就是勝利,看到了吧,這回OK了!高興吧。
?
這里我們可以總結(jié)一下,在一些比較復(fù)雜的類型無法反序列化(不能識別類型)的時候,就得考慮使用KnownTypeAttribute來標(biāo)注可能涉及到的外部類型,但如果遇到像泛型這些較為復(fù)雜的類型,就要考慮在帶數(shù)據(jù)協(xié)定的類中添加一個靜態(tài)方法,該方法返回Type 的IEnumerable,一般是Type[]就可以了,而在KnownTypeAttribute的構(gòu)造函數(shù)中使用這個方法的名字。
轉(zhuǎn)載于:https://www.cnblogs.com/GoogleGetZ/p/5752323.html
總結(jié)
以上是生活随笔為你收集整理的传说中的WCF(6):数据协定(b)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HW2.12
- 下一篇: 关于启动 SecureCRT 遇到一个致