WCF服务编程中使用SvcMap实现类型共享等技巧

【菜科解读】
调用过WCF服务的同学可能都会遇到这样的问题,同一个实体类型,不同的服务Visual Studio生成了不同的版本,例如Service1.User和Service2.User,对于C#来说,这是两个不同的类型,Service1获得的User是放不到Service2服务里去的。
手动的属性赋值来转换显然是不可取的,所以就共享类型了。
方法一、服务端和客户端共享数据契约程序集
这个方法最常用,也是大家最熟悉的方法,把WCF的数据契约放在一个独立类库里,服务端,客户端都引用这个程序集,然后在生成WCF时,选择重新使用引用程序集中的类型即可。
这个方法缺点很明显,它只有在客户端和服务端在同一个Visual Studio解决方案内才方便,否则要不断手动更新数据契约程序集。
更不用说是第三方的服务。
方法二,暴力转换类型
这个其实不是类型共享,不过也是解决这个问题的一种手段。
就是借助AutoMapper,EmitMapper这样的类库帮助快速转换类型。
下面是一个例子。
Money类型包含User实体和Currency枚举和一个数字的Amount,Money的定义
[DataContract(Namespace = Consts.Namespace)]public class Money [DataMember] public decimal Amount { get; set; } [DataMember] public Currency Currency { get; set; } [DataMember] public UserInfo User { get; set; }}Currency:
[DataContract(Namespace = Consts.Namespace)]public enum Currency [EnumMember] Euro, [EnumMember] Usd, [EnumMember] PoundSterling}UserInfo:
[DataContract(Namespace = Consts.Namespace)]public class UserInfo [DataMember] public string FirstName { get; set; } [DataMember] public string LastName { get; set; } [DataMember] public string Email { get; set; } [DataMember] public string Phone { get; set; } [DataMember] public string Id { get; set; }}对于DepositServiceNoSharp和WithdrawalServiceNoSharp这两个WCF服务版本的Money和User,可以这样添加一些扩展方法
using AutoMapper;using DepositService = Client.DepositServiceNoSharp;using Client.WithdrawalServiceNoSharp;namespace Client public static class Extensions static Extensions() Mapper.CreateMap(); Mapper.CreateMap(); Mapper.CreateMap(); Mapper.CreateMap(); public static Money ToWithdrawal(this DepositService.Money money) return Mapper.Map(money); public static DepositService.Money ToDeposit(this Money money) return Mapper.Map(money);}然后就可以轻松转换
var money = new Money Amount = 1, Currency = Currency.Usd, User = new UserInfo Email = "zhww@outlook.com", FirstName = "zhang", Id = "123", LastName = "weiwen", Phone = "110"var depositMoney = money.ToDeposit();方法三、使用SvcMap实现类型共享
其实这个才是文章的重点,前面可以忽略。
生成第一个WCF服务后,点击”显示所有文件“去编辑SvcMap文件:
找到MetadataSources节点,原来只有一个,现在把其他要引用的服务添加到这里,例如:
再右击服务,”更新服务引用“,所有服务都会生成到同一个命名空间里,实现类型共享。
WCF,服务,编程,中,使用,SvcMap,实现,类型,共享笔记本保修服务全面升级
然而,当我们的笔记本电脑出现故障时,维修服务的速度往往成为我们最关心的问题。
为了解决这个问题,笔记本保修服务全面升级,提供更快速的维修服务。
首先,我们引入了全新的维修流程,通过优化维修流程,将维修时间缩短至最低。
无论是硬件故障还是软件问题,我们的维修团队都将以最快的速度为您解决问题。
其次,我们还引入了更多的维修人员,以应对日益增长的维修需求。
无论您身在何处,我们都能够迅速派遣维修人员到达您的位置,为您提供专业的维修服务。
二、更全面的保修范围除了更快速的维修服务,笔记本保修服务还全面升级了保修范围,以更好地满足用户的需求。
首先,我们扩大了保修范围,不仅包括硬件故障,还包括软件问题。
无论是屏幕损坏、键盘故障还是系统崩溃,我们都将为您提供免费的维修服务。
其次,我们还增加了保修期限,延长了保修时间。
现在,您可以享受更长时间的免费维修服务,无需担心额外的费用。
三、更贴心的用户体验除了更快速、更全面的保修服务,笔记本保修服务还致力于提供更贴心的用户体验。
首先,我们推出了在线维修预约系统,让您可以随时随地预约维修服务。
无需等待,无需排队,您只需在家中轻松预约,我们的维修人员将按时到达。
其次,我们还提供了24小时在线客服支持,无论您遇到什么问题,都可以随时联系我们的客服团队。
我们将竭诚为您解答疑惑,提供专业的技术支持。
总结:笔记本保修服务全面升级,为用户提供更快速、更全面、更贴心的保修服务。
无论是维修速度还是保修范围,我们都将不断努力,为用户提供更好的体验。
java多线程编程小结
Java程序总是从主类的main方法开始执行。
当JVM加载代码,发现main方法后就启动一个线程,这个线程就称作"主线程",该线程负责执行main方法。
在main方法中再创建的线程就是其他线程。
如果main方法中没有创建其他线程,那么当main方法返回时JVM就会结束Java应用程序。
但如果main方法中创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main方法返回(主线程结束)JVM也不会结束,要一直等到该程序所有线程全部结束才结束Java程序(另外一种情况是:程序中调用了Runtime类的exit方法,并且安全管理器允许退出操作发生。
这时JVM也会结束该程序)。
线程的常用方法:start():线程调用该方法将启动线程,从新建态进入就绪队列,一旦享用CPU资源就可以脱离创建它的线程,独立开始自己的生命周期。
run():Thread类的run()方法与Runnable接口中的run()方法功能和作用相同,都用来定义线程对象被调度后所进行的操作,都是系统自动调用而用户不得引用的方法。
run()方法执行完毕,线程就成死亡状态,即线程释放了分配给它的内存(死亡态线程不能再调用start()方法)。
在线程没有结束run()方法前,不能让线程再调用start()方法,否则将发生IllegalThreadStateException异常。
sleep(int millsecond):有时,优先级高的线程需要优先级低的线程做一些工作来配合它,此时为让优先级高的线程让出CPU资源,使得优先级低的线程有机会运行,可以使用sleep(int millsecond)方法。
线程在休眠时被打断,JVM就抛出InterruptedException异常。
因此,必须在try-catch语句块中调用sleep方法。
isAlive():当线程调用start()方法并占有CPU资源后该线程的run()方法开始运行,在run()方法没有结束之前调用isAlive()返回true,当线程处于新建态或死亡态时调用isAlive()返回false。
注意:一个已经运行的线程在没有进入死亡态时,不要再给它分配实体,由于线程只能引用最后分配的实体,先前的实体就成为了"垃圾",并且不能被垃圾回收机制收集。
currentThread():是Thread类的类方法,可以用类名调用,返回当前正在使用CPU资源的线程。
interrupt():当线程调用sleep()方法处于休眠状态,一个占有CPU资源的线程可以让休眠的线程调用interrupt()方法"吵醒"自己,即导致线程发生IllegalThreadStateException异常,从而结束休眠,重新排队等待CPU资源。
GUI线程:JVM在运行包含图形界面应用程序时,会自动启动更多线程,其中有两个重要的线程:AWT-EventQueue和AWT-Windows。
AWT-EventQueue线程负责处理GUI事件,AWT-Windows线程负责将窗体或组件绘制到桌面。
线程同步:(用synchronized修饰某个方法,该方法修改需要同步的变量;或用volatile修饰基本变量)当两个或多个线程同时访问一个变量,并且一个线程需要修改这个变量时,应对这样的问题进行处理,否则可能发生混乱。
要处理线程同步,可以把修改数据的方法用关键字synchronized修饰。
一个方法使用synchronized修饰,当一个线程A使用这个方法时,其他线程想使用该方法时就必须等待,直到线程A使用完该方法。
所谓同步就是多个线程都需要使用一个synchronized修饰的方法。
volatile比同步简单,只适合于控制对基本变量(整数、布尔变量等)的单个实例的访问。
java中的volatile关键字与C++中一样,用volatile修饰的变量在读写操作时不会进行优化(取cache里的值以提高io速度),而是直接对主存进行操作,这表示所有线程在任何时候看到的volatile变量值都相同。
在同步方法中使用wait()、notify()、notifyAll()方法:当一个线程使用的同步方法中用到某个变量,而此变量又需要其他线程修改后才能符合本线程需要,那么可以在同步方法中使用wait()方法。
中断方法的执行,使本线程等待,暂时让出CPU资源,并允许其他线程使用这个同步方法。
其他线程如果在使用这个同步方法时不需要等待,那么它使用完这个同步方法时应当用notifyAll()方法通知所有由于使用这个同步方法而处于等待的线程结束等待。
曾中断的线程就会从中断处继续执行,并遵循"先中断先继续"的原则。
如果用的notify()方法,那么只是通知等待中的线程中某一个结束等待。
计时器线程Timer:(Timer还有很多高级操作,详细见JDK,这里做个概述)java.swing.Timer类用于周期性地执行某些操作。
有两个常用构造函数public Timer(int delay, ActionListener listener):参数listener是计时器的监视器,计时器发生振铃的事件是ActionEvent类型事件,当振铃事件发生,监视器会监视到这个事件并回调ActionListener接口中的actionPerformed(ActionEvent e)方法。
public Timer(int delay):使用该构造方法,计时器要再调用addActionListener(ActionListener listener)方法获得监视器。
如果想让计时器只震动一次,可以让计时器调用setRepeats(boolean b)方法,参数b取false即可。
计时器还可以调用setInitialDelay(int delay)方法设置首次振铃的延时,如果没有设置首次振铃默认延时为构造函数中的参数delay。
还可以调用getDelay()和setDelay(int delay)获取和设置延时。
计时器创建后调用start()启动,调用stop()停止,即挂起,调用restart()重新启动计时器,即恢复线程。
java有点不同,实现多线程有两种方式:继承类Thread, 和 实现接口Runnable。
thread类有一个run函数,它是线程的入口,当启动一个新线程是,就从这个函数开始执行;public class ThreadTest extends Thread{ public void run() for (int i=0;i注意线程是调用start()来开始的。
Runnable有一点点不同,实现这个类的时候和Thread一样,但是创建线程的时候还是放入一个Thread中创建:public class RunnableTest implements Runnable private int cnt; public RunnableTest(int n) super(); cnt = n; public void run() for (int i=0;ijoin(): 强制等待线程执行完毕。
例如如果在主线程里面加一句ta.join(),那么主线程会一直等待ta执行返回才接着执行后面的代码。
但是在join之前已经创建的其他线程,则不会受影响,继续执行。
interrupt(): 挺有意思的一个函数,如果线程在执行sleep()函数 ,则打断它(以让sleep()函数抛出一个异常的方式中断),执行后面的语句。
setDaemon(true):设置为守护进程。
守护进程的优先级是最低的,如果一个程序只剩下守护进程,那么它就中断所有守护进程而退出。
最常见的情况是,如果创建的全部是守护进程,那么当主函数main执行完毕后,就立刻终止所有线程而退出。
synchronized同步符号用法: 保证同一时刻,某段代码只有一个线程在执行。
wait()和notify(),notifyAll():让线程等待/唤醒。
这两个函数比较奇怪,目前我不是很熟练,要配合synchronized符号使用,请看下面这个生产者-消费者例子(网上直接贴来的,写的挺好的):public class tt { public static void main(String[] args) { Storage s = new Storage(); Producer p = new Producer(s); Consumer c = new Consumer(s); Thread tp = new Thread(p); Thread tc = new Thread(c); tp.start(); tc.start();class Consumer implements Runnable {//消费者 Storage s = null; public Consumer(Storage s){ this.s = s; public void run() { for(int i=0; i java,多,线程,编程,小结,每个,Java,程序,都,