Visual Studio 和基础Microsoft NET Framework 提供了新工具并支持Windows Communication Foundation(WCF)它们并未改变WCF (与NET Framework 一起发布)的基本功能而是对其进行了扩展和完善
Visual Studio 可自动执行WCF手动任务包括更新代理引用和消除重复任务(例如创建简单托管项目)Visual Studio还能解决跨目标和数据协定类型共享等一些困难问题在本专栏中我将逐步介绍其新功能及优势并对其任何缺陷和解决方法做出解释尽管我将在此使用C#项目设置但除非我另行说明否则所有设置同样适用于Visual Basic
NET Framework跨目标
Visual Studio的早期版本通常针对随其一起提供的 NET Framework 版本例如Visual Studio 只能生成针对 NET Framework 的程序集而此惯例并不能反映大多数开发人员所面临的真实情况通常开发人员需要在维护针对早期版本的 NET 而编写的旧版应用程序的同时还要在其新版应用程序中使用新版 Visual Studio
此外此惯例还意味着开发人员在维护为早期版本的 NET Framework 而编写的应用程序时无法从效率增强功能(例如 Visual Studio 中引入的代码重构支持)中获益
问题在于 NET Framework 各版本不支持跨目标功能您要么必须安装多个版本的 Visual Studio要么使用独立的测试和部署内部版本进行补偿Visual Studio 尝试通过为多个版本的NET Framework提供充分支持(虽然不完美)来解决这一问题由于实际上NET Framework 和NET Framework 使用的CLR版本与NET Framework 使用的相同唯一的区别在于新引用的程序集因此Visual Studio仍可针对相同运行库而为NET Framework版本和(其中NET Framework版本号对应的是发行版本而不是运行库版本运行库版本仍为CLR )提供跨目标功能
在Visual Studio 中Properties(项目)的Application(应用程序)窗格包含一个称为Target Framework(目标框架)的新组合框通过该组合框您就可以针对NET Framework版本和(参见图)
)this
width=
;
>图
Visual Studio
中的目标框架属性
Target Framework值仅在开发时有效而在运行时无效(您的程序集仍指向NET CLR)您选择的值表示您构建程序集时可针对的NET Framework的最早版本新项目默认被配置为针对NET Framework 如果添加引用则会变得有些复杂如果在引用较高版本程序集时降低Target Framework版本Visual Studio 将提示您引用出错和内部版本失败Visual Studio 不允许您向其所需Framework版本高于现有项目的NET Framework程序集添加引用如果您向版本更高的同一解决方案中的其他项目添加引用Visual Studio 将警告您可能会发生沖突如果通过浏览程序集来添加引用Visual Studio 将不会干预您进行操作
在语言和跨目标方面请注意您可以在C#中(而不是Visual Basic中)通过限制编译器版本来限制使用NET Framework 或项目中诸如匿名类型和扩展方法等功能您可以转至Build(内部版本)窗格然后单击Advanced(高级)按钮并选择ISO(C# )作为语言版本(而不是尚未标准化的默认版本)来执行此操作
在Visual Studio 中打开Visual Studio WCF项目时升级过程中框架版本保持为 实际上这可以正常运行(请记住基础运行库版本并未改变)但我建议根据需要手动将其设置为版本 或
使用新项目模板时Target Framework 版本是最重要的因素WCF 工作流和整合项目必须针对 NET Framework 进行构建Service Library 项目要求针对 NET Framework 或 Add Service Reference(添加服务引用)功能仅当为项目选择 Framework 版本 或 时可用本专栏稍后将介绍此功能
WCF 提供的主机
Visual Studio 附带了一款名为 WcfSvcHostexe 的现成的通用服务主机它位于 C:\Program Files\Microsoft Visual Studio \Common\IDE 中为了方便使用我建议将该位置添加到系统的 Path 变量中WcfSvcHost 是一种简单的命令行实用工具可接受两个参数一个是指向包含一个或多个服务类的 NET 程序集的文件路径另一个是指向托管nfig 文件的文件路径例如
WcfSvcHostexe /service:MyServicedll /config:nfig
指定的服务程序集可以是类库程序集 (DLL)也可以是应用程序程序集 (EXE)WcfSvcHost 将启动一个新进程该进程将自动托管指定nfig 文件的服务部分中列出的所有服务类请注意这些服务类及其服务约定和数据协定不必是公共类型可以是内部类型此外自动托管的服务不需要提供任何元数据但是它们可以发布元数据(如果选择发布)
WcfSvcHost 是一种以桌面任务栏图标驻留的 Windows 窗体应用程序若要关闭主机只需从任务栏图标上下文菜单中选择Exit(退出)即可使用这种方式终止托管不太妥当因为 WcfSvcHost 将中止当前正在进行的所有调用客户端很可能会收到异常如果单击 WcfSvcHost 任务栏图标将出现一个对话框其中列出托管的所有服务(参见图 )
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
WcfSvcHost 服务列表
该对话框还显示服务的状态及其元数据地址您可以将这些信息复制到剪贴板稍后向服务添加引用时可能会用得到关闭 WcfSvcHost UI 只是将其折叠回任务栏
WcfSvcHost 的目的就是在开发过程中不再需要使用独立托管程序集来配合服务库诸如托管项目等的开发工作是一种重复任务这些主机通常包含大量相同的代码行当有多个服务库时这些重复代码容易导致解决方案变得臃肿为了便于开发和测试可以将 WcfSvcHost 直接集成到您的 Visual Studio 服务库项目中在项目属性的Debug(调试)窗格中将 WcfSvcHostexe 指定为要启动的外部程序然后将您的类库名及其nfig 文件(自动生成并自动复制到 bin 文件夹)指定为参数
完成后当您运行类库(完成上述操作后才能执行运行)时它将借助该进程附带的调试器由 WcfSvcHost 自动托管停止调试时Visual Studio 将以不妥当的方式中止托管
您甚至可以在 NET Framework 应用程序中与 Visual Studio 项目一起使用 WcfSvcHost由于 WcfSvcHost 只需要 NET Framework 因此只需从安装了 Visual Studio 的计算机上复制 WcfSvcHost 即可为了使用更加方便建议您将 WcfSvcHost 添加到 NET Framework 计算机上的全局程序集缓存 (GAC) 中
WcfSvcHost 的最后一个功能是能够自动启动客户端应用程序甚至能够为客户端提供特定于该应用程序的可选参数
WcfSvcHostexe /service:MyServicedll /config:nfig
/client:MyClientexe /clientArgs:ABC
此功能对于在自动测试甚至是简单部署的情况下启动主机和客户端非常有用
WcfSvcHost 的最大缺陷是只适用于简单情况例如在打开主机实例之前无需以编程方式访问主机实例的情况或在其打开之后以编程方式访问其事件模型的情况与使用 IIS 或 Windows Activation Service (WAS) 进行托管不同WcfSvcHost 没有对等的服务主机工厂支持因此不具备动态添加基址配置终结点中止调用以及在主机级别配置自定义行为等功能通过我对 WCF 的使用体验发现除了最简单的情况之外所有其他情况中最终都需要以编程方式访问主机实例因此我并不将 WcfSvcHost 视为一种成熟高效的主机而我自己执行 WAS 或进行专用自托管
WCF 提供的测试客户端
除服务主机外Visual Studio 还随附了一个用于进行基本测试的简单通用的测试客户端您可以使用它调用大多数服务上的操作正常安装后测试客户端 WcfTestClientexe 位于 WcfTestClientexe is found after normal installation at C:\Program Files\Microsoft Visual Studio \Common\IDE 下您必须为 WcfTestClient 提供一个命令行参数其中包含要测试的服务的元数据地址
Wc//localhost:/
您可以指定任何元数据地址例如 HTTPGET 或者 HTTPTCP 或 IPC(命名管道)上的元数据终结点也可以指定多个元数据地址
WcfTestClientexe
WcfTestClient 是一个 Windows Forms 应用程序(参见图 )在此图中左侧的树控件包含测试的服务及其终结点您可以详细查看某个终结点的约定并选择某项操作特定于该调用的信息将显示在右侧窗格的选项卡中图 所示为一个简单约定及其实现的示例
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
使用WcfTestClient
您可以在方法选项卡的Request(请求)部分中输入作为操作参数的一个整数和一个字符串如图 所示单击Invoke(调用)按钮时它将向服务调度调用并在Response(响应)中显示返回值或输出参数如果是单向操作WcfTestClient 将在消息框中通知您已成功调度此操作如果出现异常WcfTestClient 将在消息框中显示异常信息并让您发出其他调用
Figure 示例服务
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
[ServiceContract]
interface IMyContract
{
[OperationContract]
string MyMethod(int someNumberstring someText);
}
class MyService : IMyContract
{
public string MyMethod(int someNumberstring someText)
{
return Hello;
}
}
WcfTestClient 不使用测试服务来维护传输层会话(或任何其他会话)所有调用均在新代理实例上进行此外所有调用均异步进行这样 UI 能随时进行响应但是尽管是异步调用WcfTestClient 只允许一次调度一个调用
WcfTestClient 从代理文件(包括nfig 文件)以静默方式创建程序集然后从临时位置加载该程序集如果单击树中的Config File(配置文件)项您可以获取该nfig 文件(添加服务引用时生成的同一nfig 文件)并可以将其显示其选项卡中
与早期的 Visual Studio ASMX Web 服务测试页不同通过 WcfTestClient 您可以借助枚举类或结构(每个类或结构都是其他类或结构的组成部分)等复合参数甚至是参数集合和参数数组来调用操作只需展开Request(请求)部分中的项从下拉列表中设置其值(例如枚举值)并进行调用即可如果操作接受集合或数组您还需要设置其长度例如图 显示了以下操作的结果请求和响应
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
指定数组长度和值
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>[OperationContract]
bool ProcessNumbers(int[] numbers]
类似地Response(响应)窗格将包含所有返回的复合值或输出参数这样我们发现了 WcfTestClient 的一个缺陷为了指定要测试的不同服务您必须先关闭并在更改命令行参数后重新启动 WcfTestClient如果能同时在 GUI 中提供服务地址则可能会很好地缓解这个问题
您可以直接将 WcfTestClient 集成到您的 Visual Studio 解决方案中首先将类库项目添加到解决方案并删除所有引用文件夹和源文件(因为您不需要这些项)然后将 WcfTestClientexe 设置为外部启动程序并提供一个或多个测试服务的一个或多个元数据地址例如 IIS 或 WAS 托管项目的 svc 地址或者就此而言解决方案内部或外部主机项目的任何其他元数据地址
请注意如果计算机上只安装了 NET Framework 则您不能在其上使用 WcfTestClient因为 WcfTestClient 需要使用内部 NET Framework 树网格控件(用于表示复合参数的控件)
当然您可以在一个步骤中结合 WcfTestClient 和 WcfSvcHost这样即可自动托管服务库中的服务并对其进行测试
WcfSvcHostexe /service:MyServicedll /config:nfig
/client:WcfTestClientexe
///localhost:/
但是可以使用 WcfSvcHost 指定元数据参数默认情况下WcfSvcHost 将向指定客户端应用程序传送它在服务nfig 文件中找到的元数据地址仅当服务未提供自己的元数据或您希望测试客户端使用其他地址时才应显式指定元数据地址此外如果服务nfig 文件包含给定服务的多个元数据终结点则这些终结点将按以下优先顺序提供HTTPTCPIPC 和 HTTPGET您可以在 Visual Studio 中合并这些步骤以进行无缝托管和测试体验将 WcfSvcHostexe 指定为启动程序并将nfig 文件和 WcfTestClientexe 指定为客户端
WCF 服务库
作为 Target Framework 的一项功能Visual Studio 提供了多个新的 WCF 项目模板通过New Project(新建项目)对话框中的组合框您可以指定 Target Framework 的版本( 或 )如图 所示
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
WCF 项目模板
如果选择 Framework 则没有任何新模板可用Framework 中提供了一个称为 WCF 服务库的新项目模板此项目类型只是 WcfSvcHost 和 WcfTestClient 的预构建用法与我前面提到的技术(将两者合二为一)非常类似请注意使用 WCF 服务库模板就不需要将 WcfSvcHostexe 指定为启动程序或nfig 文件因为项目文件包含适用于 WCF 服务库的新 ProjectTypeGuids 元素
但是该模板有一个负面影响停止调试程序不会终止测试客户端时间久了您的桌面会由于孤立客户端而变得杂乱要解决此问题只需还原到前面清晰介绍的手动步骤
WCF 服务库还提供了一个用于服务约定服务约定的实施及匹配的nfig 文件的简单模板
利用聚合服务库您可以通过 WCF 终结点实现 RSS 源并且可以从返回源的简单服务约定服务约定的实施及匹配的nfig 文件着手操作您可以托管和显示自己的源与托管和显示任何其他服务一样聚合终结点使用新的 WebHttpBinding 绑定此新绑定旨在用于接收 Web 请求而不能用于常规服务调用
使用顺序工作流服务库模板您可以将终结点的约定操作作为工作流活动来实现或者将工作流显示为服务项目将包含一个用于实现简单约定和匹配的nfig 文件的顺序活动尽管客户端也将与类似传统终结点的终结点进行交互但其实现完全是工作流驱动的
状态机工作流服务库模板使用状态机而不是顺序工作流来实施其操作(触发状态转换)工作流项目模板使用 WcfSvcHost 和 WcfTestClient如同普通 WCF 服务库那样工作流模板还使用新的上下文绑定对工作流实例 ID 的传递进行管理从而支持持续工作流我将在以后的专栏中详细介绍这些绑定
添加服务引用
Visual Studio extensions for NET Framework 提供了一项用于向 WCF 服务添加引用的基本功能而不具有 SvcUtil 的许多高级功能Visual Studio 具有一个新的服务引用对话框如图 所示
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
添加服务引用
对话框
您可以在任何项目中打开此新对话框方法是右键单击解决方案资源管理器中项目内的任意位置然后从上下文菜单中选择Add Service Reference(添加服务引用)请注意必须将项目配置为针对 NET Framework (及更高版本)才能启用此选项
在Add Service Reference(添加服务引用)对话框中首先需要指定服务元数据地址(不是服务 URL如对话框中所述)然后单击Go(执行)查看可用服务终结点(不是服务如标记所示)必须指定命名空间(如 MyService)才能包含生成的代理然后单击OK(确定)生成代理并更新nfig 文件请注意在多数情况下Visual Studio 不是足够的智能来推断最清楚的绑定值因此它将通过声明绑定的所有默认值来删除nfig 文件Visual Studio 的未来版本中将会解决此问题如果您关注对nfig 文件的维护请先打开nfig 文件再添加引用然后执行一次撤消 (Ctrl+Z) 操作最后手动将nfig 文件条目添加到客户端部分中
只要 WCF 服务位于网站项目或某个新 WCF 服务库中您就可以使用Discover(搜索)按钮在自己的解决方案中查找这些服务如果位于网站项目中Visual Studio 将检索 IIS 中的元数据或启动基于文件系统的 ASPNET 开发服务器如果位于 WCF 服务库中则 WCF 将自动启动其主机 (WcfSvcHost) 以便获取元数据
可以通过Advanced(高级)按钮打开设置对话框从而调整代理生成如同使用 SvcUtil(参见图 )一样通过使用更直观的选项您可以配置生成的代理和约定(公共或内部)的可见性可以为数据类型生成适用于高级互操作方案的消息约定在此方案中必须遵从现有消息格式(通常为自定义)并可以单击Add Web Reference(添加 Web 引用)按钮将引用转换为旧 ASMX Web 服务引用
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
服务引用高级选项
Generate asynchronous operations(生成异步操作)复选框可以为导入的约定中的每个操作添加一对匹配的 Begin 和 End 元素这两个元素允许客户端在工作线程中异步发出调用并且通过提供完成回调方法或阻止完成来允许客户端稍后与操作完成进行同步例如假设约定的定义如下
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
[ServiceContract]
interface ICalculator
{
[OperationContract]
int Add(int numberint number);
}
则导入的约定将如图 所示
Figure 导入的异步约定
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
[ServiceContract]
interface ICalculator
{
[OperationContract]
int Add(int numberint number);
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAdd(int numberint number
AsyncCallback callbackobject asyncState);
int EndAdd(IAsyncResult result);
//Rest of the methods
}
异步调用的匹配客户端代码将类似于如下所示
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
CalculatorClient proxy = new CalculatorClient();
int sum;
AsyncCallback completion = (result)=>
{
sum = proxyEndAdd(result);
DebugAssert(sum == );
proxyClose();
};
proxyBeginAdd(completionnull);
虽然您可以按原样使用这些方法但是提供给 Begin 的完成回调是从线程池中的线程调用的如果使用回调访问某些与特定线程相关联的资源则这样做会出现严重问题Windows 窗体(或 WPF)应用程序即为典型示例此应用程序异步调度较长的服务调用(避免阻止 UI)然后希望使用调用结果来更新 UI不允许使用原始 Begin 进行更新因为只允许 UI 线程更新 UI为了更好地处理此情况已用受保护的 InvokeAsync 方法扩展了 ClientBase 基类该方法可以获取客户端的同步上下文并将其用于调用完成回调如图 所示
Figure ClientBase 中的异步回调管理
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
public abstract class ClientBase : {
protected delegate IAsyncResult BeginOperationDelegate(
object[] inValuesAsyncCallback asyncCallbackobject state);
protected delegate object[] EndOperationDelegate(IAsyncResult result);
//Picks up sync context used for completion callback
protected void InvokeAsync(BeginOperationDelegate beginOpDelegate
object[] inValues
EndOperationDelegate endOpDelegate
SendOrPostCallback opCompletedCallback
object userState)
{}
//More members
}
ClientBase 还提供了一个事件参数帮助器类和两个用于启动和结束异步调用的专用委托生成的代理类由 ClientBase 派生而来此代理类将使用这些基本功能代理将具有一个 Completed 公共事件(该事件使用特定于异步方法结果的强类型事件参数类)和两个 Async 方法(用于异步调度调用)
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
partial class AddCompletedEventArgs : AsyncCompletedEventArgs
{
public int Result
{get;}
}
class CalculatorClient : ClientBaseICalculator{
public event EventHandler AddCompleted;
public void AddAsync(int numberint numberobject userState);
public void AddAsync(int numberint number);
//Rest of the proxy
}
客户端还可以为 Completed 事件订阅事件处理程序以便在完成时调用此事件处理程序使用 Async 与 Begin 的主要差别在于Async 方法获取客户端的同步上下文并在该同步上下文中激发 Completed 事件如图 所示
Figure 针对用户界面友好的异步调用的调用
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
partial class CalculatorForm : Form
{
CalculatorClient m_Proxy;
public MyClient()
{
InitializeComponent();
m_Proxy = new CalculatorClient();
m_ProxyAddCompleted += OnAddCompleted;
}
void CallAsync(object senderEventArgs args)
{
m_ProxyAddAsync(); //Sync context picked up here
}
//Called on the UI thread
void OnAddCompleted(object senderAddCompletedEventArgs args)
{
Text = Sum = + argsResult;
}
}
通过Collection(集合)类型组合框您可以指定如何向客户端显示在服务元数据中找到的某些类型的集合和数组例如如果服务操作返回 IEnumerableIList 或 ICollection 集合中的某一个则默认情况下代理会将其显示为数组例如以下服务端操作
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>[OperationContract]
IEnumerable GetNumbers();
将在代理上表示为
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>[OperationContract]
int[] GetNumbers();
但是您可以请求 Visual Studio 使用其他集合(例如用于进行数据绑定的 BindingListListCollection 和 LinkedList 等)如果可以进行转换代理将使用请求的集合类型而不是数组如下所示
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>[OperationContract]
List GetNumbers();
字典也具有类似功能通常情况下如果服务操作返回可序列化的字典如下所示
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>
[Serializable]
class MyDictionaryT> : IDictionaryT> {}
[OperationContract]
MyDictionarySTRING> GetDictionary();
代理类随后会将该字典表示为 DictionaryK>这是以下 Dictionary 集合类型组合框的默认值
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>[OperationContract]
DictionarySTRING> GetDictionary();
但是您可以请求其他字典类型(如 SortedDictionaryK>HashTable 或 ListDictionary)代理将改为使用这些字典(如果可能)
cellSpacing= borderColorLight=black borderColorDark=#ffffff cellPadding= width= align=center>ee>[OperationContract]
SortedDictionarySTRING> GetDictionary();
综上所述新服务引用最重要的功能就是能够在程序集之间共享数据协定类型使用 Visual Studio 如果客户端将服务引用添加到两个支持相同数据协定的独立服务中那么客户端将获得两个类型完全相同(表示相同数据协定)的不同服务引用使用 Visual Studio 默认情况下如果客户端引用的任何程序集所具有的数据协定类型与引用服务的元数据中显示的数据协定类型相匹配则 Visual Studio 将不会再次导入该类型有必要再次强调一下现有数据协定引用必须位于另一个引用程序集中而不是位于客户端项目本身中Visual Studio 的未来版本中可能会解决此限制目前解决方法和最佳实践都很明显将所有共享数据协定都构建到指定的类库中并让所有客户端都引用该程序集
通过服务引用的高级设置对话框您可以配置数据协定共享默认情况下Reuse types in the referenced assemblies(重用引用程序集中的类型)复选框处于选中状态但您可以关闭此功能不管复选框的名称是什么此复选框都将只能共享数据协定而不能共享服务约定使用复选框下面的单选按钮(参见图 )还可以指示 Visual Studio 在所有引用的程序集中重用数据协定或者通过选中列表中的特定程序集来限制共享这些程序集
添加引用后项目将具有一个新文件夹 Service References该文件夹中显示了每个引用的服务的服务引用项(参见图 )
cellSpacing=
borderColorLight=#
borderColorDark=#ffffff bgColor=#ddddd align=center>image onmousewheel=
javascript:return big(this)
src=
http://img
educity
cn/img_
/
/
/
gif
onload=
javascript:if(this
width>
)this
width=
;
>图
服务引用文件夹
随时可以右键单击引用并选择Update Service Reference(更新服务引用)来重新生成代理并更新客户端的nfig 文件由于服务引用项中还包含一个记录了所使用的原始元数据地址的文件因此可以执行此操作
还可以选择Configure Service Reference(配置服务引用)打开一个对话框该对话框与添加引用时使用的高级设置对话框类似通过配置服务引用对话框您可以更改服务元数据地址以及其他高级代理设置