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

作者:小菜 更新时间:2025-02-27 点击数:
简介:调用过WCF服务的同学可能都会遇到这样的问题,同一个实体类型,不同的服务Visual Studio生成了不同的版本,例如Service1.User和Servic

【菜科解读】

调用过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,实现,类型,共享

笔记本保修服务全面升级

专业的在线重装系统软件 全新设计 / 全新代码编写 / 全新支持所有机型 全新支持Window 11 安装 简介:笔记本保修服务全面升级工具原料:品牌型号:Apple MacBook Pro 2020操作系统版本:macOS Big Sur软件版本:AppleCare+一、更快速的维修服务随着科技的不断发展,笔记本电脑已经成为我们生活中不可或缺的一部分。

然而,当我们的笔记本电脑出现故障时,维修服务的速度往往成为我们最关心的问题。

为了解决这个问题,笔记本保修服务全面升级,提供更快速的维修服务。

首先,我们引入了全新的维修流程,通过优化维修流程,将维修时间缩短至最低。

无论是硬件故障还是软件问题,我们的维修团队都将以最快的速度为您解决问题。

其次,我们还引入了更多的维修人员,以应对日益增长的维修需求。

无论您身在何处,我们都能够迅速派遣维修人员到达您的位置,为您提供专业的维修服务。

二、更全面的保修范围除了更快速的维修服务,笔记本保修服务还全面升级了保修范围,以更好地满足用户的需求。

首先,我们扩大了保修范围,不仅包括硬件故障,还包括软件问题。

无论是屏幕损坏、键盘故障还是系统崩溃,我们都将为您提供免费的维修服务。

其次,我们还增加了保修期限,延长了保修时间。

现在,您可以享受更长时间的免费维修服务,无需担心额外的费用。

三、更贴心的用户体验除了更快速、更全面的保修服务,笔记本保修服务还致力于提供更贴心的用户体验。

首先,我们推出了在线维修预约系统,让您可以随时随地预约维修服务。

无需等待,无需排队,您只需在家中轻松预约,我们的维修人员将按时到达。

其次,我们还提供了24小时在线客服支持,无论您遇到什么问题,都可以随时联系我们的客服团队。

我们将竭诚为您解答疑惑,提供专业的技术支持。

总结:笔记本保修服务全面升级,为用户提供更快速、更全面、更贴心的保修服务。

无论是维修速度还是保修范围,我们都将不断努力,为用户提供更好的体验。

java多线程编程小结

每个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,程序,都,

加入收藏
上一篇:vivo最新款手机是哪款
下一篇:没有了
               

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

点击下载文档

格式为doc格式

  • 账号登录
社交账号登录