我们继续,上一回我们了解了数据协定的一部分内容,今天我们接着来做实验。好的,实验之前先说一句:实验有风险,写代码须谨慎。

实验开始!现在,我们定义两个带数据协定的类——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对象,而我们的服务定义如下:

    [ServiceContract(Namespace = "MyNamespace")]public interface IService{[OperationContract]Student GetStudentInfo();}

    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;return stu;}}

方法返回的Student对象,那么,我们来测试一下,AddrInfo能不能被成功序列化和反序列化。下面是注册和启动服务的代码:

        static void Main(string[] args){// 服务器基址Uri baseAddress = new Uri("http://localhost:1378/services");// 声明服务器主机using (ServiceHost host = new ServiceHost(typeof(MyService), baseAddress)){// 添加绑定和终结点WSHttpBinding binding = new WSHttpBinding();host.AddServiceEndpoint(typeof(IService), binding, "/test");// 添加服务描述host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });try{// 打开服务host.Open();Console.WriteLine("服务已启动。");}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 = "学生姓名:{0}\n联系电话:{1}\n" +"地址信息:-----------\n" +"省份:{2}\n" +"市区:{3}\n" +"详细地址:{4}";Console.WriteLine(msg, stu.Name, stu.Phone, stu.Address.Province, stu.Address.City, stu.Address.DetailAddr);Console.ReadKey();}

其运行结果如下:

下面我们继续实验。

每个学生可能有多个学科的成绩,因此,我们为学生类再添加一个成绩属性。

    [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("数学", 38f);m_scores.Add("历史", 77.6f);m_scores.Add("地理", 82.3f);stu.Scores = m_scores;return stu;}}

客户端测试代码改为:

        static void Main(string[] args){WS.ServiceClient cli = new WS.ServiceClient();WS.Student stu = cli.GetStudentInfo();string msg = "学生姓名:{0}\n联系电话:{1}\n" +"地址信息:-----------\n" +"省份:{2}\n" +"市区:{3}\n" +"详细地址:{4}";Console.WriteLine(msg, stu.Name, stu.Phone, stu.Address.Province, stu.Address.City, stu.Address.DetailAddr);Console.WriteLine("---------------------------------------");Console.WriteLine("学生成绩单:");Dictionary<string, float> scores = stu.Scores as Dictionary<string, float>;foreach (var item in scores){Console.Write("{0}:{1}\n", item.Key, item.Value);}Console.ReadKey();}

现在来测试,就会发生异常,因为我们为Student类加的成绩属性是object类型,而我们在协定方法中给它赋的是 Dictionary<string, float>类型,这样一来,就算可以序列化也不能被反序列化,因为Dictionary<string, float>无法识别。

现在,我们再为Student类添加一个KnownType特性,看它能不能识别。

[DataContract]
[KnownType(typeof(Dictionary<string, float>))]
public class Student
{
。。。。。
}

这时候,再运行一下。

很可惜,还是报错了,

怎么办呢?不要放弃,我们继续把学生类修改一下。

    [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方法是静态方法,KnownType的构造函数中传递该方法的名字。看看这回调用能否成功?

坚持就是胜利,看到了吧,这回OK了!高兴吧。

这里我们可以总结一下,在一些比较复杂的类型无法反序列化(不能识别类型)的时候,就得考虑使用KnownTypeAttribute来标注可能涉及到的外部类型,但如果遇到像泛型这些较为复杂的类型,就要考虑在带数据协定的类中添加一个静态方法,该方法返回Type 的IEnumerable,一般是Type[]就可以了,而在KnownTypeAttribute的构造函数中使用这个方法的名字。

转载于:https://www.cnblogs.com/GoogleGetZ/p/5752323.html

传说中的WCF(6):数据协定(b)相关推荐

  1. 传说中的WCF(5):数据协定(a)

    在第4篇中,咱们了解了发送/接收SOAP头,从本篇开头,我们不妨更深入地去探求一下有关WCF中的消息到底是啥玩意儿.WCF庞大而复杂,而从 MSDN文档中,你会看到许多很专业很抽象的东西,你不禁会问, ...

  2. 传说中的WCF:消息拦截与篡改

    我们知道,在WCF中,客户端对服务操作方法的每一次调用,都可以被看作是一条消息,而且,可能我们还会有一个疑问:如何知道客户端与服务器通讯过程中,期间发送和接收的SOAP是什么样子.当然,也有人是通过借 ...

  3. 重温WCF之数据契约和序列化(四)

    一.数据契约 1.使用数据协定可以灵活控制哪些成员应该被客户端识别. [DataContract]public class Employee{[DataMember]public string Nam ...

  4. DataContract 添加到 DataContractSet,因为已经存在数据协定名称也为命名空间

    因为我使用了泛型数据合同,使用的名字又是同一个,所以就会报个错误, System.InvalidOperationException: 在调用 WSDL 导出扩展过程中引发异常: System.Ser ...

  5. WF是什么系列之[基于WF与WCF构建数据逻辑层]

    WF是什么,许多对NET技术有了解的人能说出一点,但又说不清楚 不论你认为WF是什么,但不要与Jbpm ,Shark ,Biztalk,SharePoint 这些产品做比效,这些产品有共同的特点就是面 ...

  6. ExtJs学习笔记(21)-使用XTemplate结合WCF显示数据

    个人认为,XTemplate是ExtJs中最灵活的用来显示数据的组件,有点类似aspx中的Repeater控件,显示数据的模板完全可以由用户以html方式来定制. 先给一个官方的静态示例(稍微改了下) ...

  7. 【转】解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接...

    开发中所用的数据需要通过WCF进行数据传输,结果就遇到了WCF大量传输问题 也就是提示System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接 网上解决 ...

  8. WCF 之 数据契约

    前面几篇讲的都只能传递string类型的简单参数,数据契约就是用来解决如传递一个带有多个属性的Class类型的对象的. WCF推荐使用数据契约的方式实现数据的序列化.这部分的内容很好理解但是很重要,先 ...

  9. 关于silverlight+MVVM+WCF保存数据出错的问题

    最近在用silverlight开发一个项目,由于接触比较浅,做起来真是一个头两个大.一个简单的数据更新操作费了好多天,哎 期间的点点滴滴打算记录起来,就当是给自己的纪念吧,哈哈~. 单表更新:表结构如 ...

最新文章

  1. centos下设置node.js开机启动(并且启动自己的项目js)
  2. matlab练习程序(高斯牛顿法最优化)
  3. android从放弃到精通 第三天 我还活着
  4. 将oracle select * from all_tab_comments where comments like ‘%XXXX%‘查询结果转为select语句
  5. ThreadLocal相关
  6. 解析邮件归档技术 保护企业邮件安全(三)
  7. 云计算-从基础到应用架构系列-云计算的演进
  8. 删除单元格_VBA(实验1)用VBA 删除某列空单元格的3种方法:删除法,转移到其他列方法,数组方法...
  9. Android  Doze and App Standby模式详解
  10. a+aa+...+aaa..aa表达式输出
  11. jmx.JmxAdminException
  12. LintCode—两数组的交(547)
  13. Anaconda版本选择 Python3.6版本的Anaconda下载
  14. 上瘾啦,又用 Python 制作销售数据可视化看板
  15. 泰勒展开式求sinx近似值
  16. 【元宵节】中国人民大学与加拿大女王大学金融硕士项目与你的那份“缘”
  17. HTML5网页设计成品_中华传统文化网页题材_诗词网页4页_web课程设计网页制作
  18. Proxifier使用代理ip教程
  19. hadoop2.8配置_Hadoop 2.8集群安装及配置记录
  20. 解决问题“The App ID ‘XXXXX‘ appears to be in use by the App Store, so it can not be removed at this ti”

热门文章

  1. 说说我的ID:fxh7622
  2. ubuntu19.10升级
  3. 已经导入依赖,但是Cannot resolve symbol“registerFunction“
  4. FIR和IIR的区别+差分方程的单位冲激响应(matlab图解)
  5. 神经网络中的病态曲率-Pathological Curve-举例
  6. error: missing or invalid dependency detected while loading class file 'RDD.class'.
  7. python2.7+opencv3.1人脸识别
  8. 深圳乐易网络有限公司机试题String to Integer (atoi)
  9. 爬虫爬出来的数据不全_斥巨资学完Python数据分析后,给运营人总结7个小建议...
  10. html做转盘指针被压住,爸爸特制“写作业”转盘,被儿子反套路:愿赌服输!...