构建 BizTalk Server 2006 货币转换器自定义函数






4.76/5 (17投票s)
您将学习如何使用 Web 服务构建 BizTalk Server 2006 货币转换器自定义 Functoid,并了解标准 functoid 的介绍。
目录
- 引言
- 知识先决条件和软件要求
- BizTalk Server 2006 映射器
- BizTalk Server 2006 标准 Functoid
- Functoid 配置
- 自定义 Functoid 架构
- 自定义 Functoid 设计
- 货币转换器 Functoid 开发
- 在 GAC 中注册货币转换器 Functoid
- 将货币转换器 Functoid 添加到工具箱
- 货币转换器 Functoid 使用
- Using the Code
- 关注点
- 结论
引言
BizTalk Server 2006 大约有 80 个 functoid 或函数;这些 functoid 在构建映射时很有用;稍后会详细介绍。BizTalk Server 2006 映射器 IDE 与 VS.NET 2005 IDE 相同;当您构建映射时,您将处于您习惯的相同环境中,如果您打开一个映射,functoid 工具箱将显示所有标准和自定义 functoid。标准 functoid 根据其功能进行了整齐的分类,但有时您拥有的 functoid 库不够用,因此您将选择构建自己的 functoid。在本文中,我将向您介绍 BizTalk Server 2006 映射器,并将尝试解释和简化 BizTalk Server 2006 提供的标准 functoid,并提供一个数据库查找 functoid 的实际示例。然后,在检查自定义 functoid 的架构之后,我们将构建一个自定义 functoid。我们将构建的 functoid 是一个货币转换器 functoid。我试图提出一个有用且可重用的 functoid,您以后可能会使用它。此 functoid 基于提供汇率的 Web 服务。此外,您还将学习如何将 functoid 安装到 GAC(全局程序集缓存)中,并将其添加到您的工具箱中。那么,让我们开始 functoid 之旅吧。
知识先决条件和软件要求
- 知识
- BizTalk Server 核心原理;例如消息传递、如何创建架构、映射等。我将尽力解释这些概念,但如果您有先前的经验,那将是极好的。
- WebServices 核心原理。
- 软件要求
- Visual Studio .NET 2005。
- BizTalk Server 2006;这些是我的版本,我想您可以使用 VS.NET 2003 和 BizTalk 2004。
BizTalk Server 2006 映射器
BizTalk 映射器只是一个用于定义输入源架构和目标架构之间关系的工具。换句话说,它使用一个精致的设计器,直接在 VS.NET 2005 中将元素、属性、记录等相互绑定。您可以直接将字段元素连接到任何其他架构元素,或者您可以处理输入数据并将其发送到目标元素;处理是通过 functoid 维护的。例如,如果目标架构只允许一个*Name* 字段元素,而源架构有两个名称字段,*firstName* 和 *lastName*,您可以使用 *String Concatenate* functoid,它接受名字和姓氏。它实际上接受 1 到 100 个参数。然后您可以从此 functoid 输出到目标架构元素(在本例中为 *Name*)创建链接。
BizTalk 以 *.btm*(BizTalk Map)文件扩展名保存映射,这是一个基于 XML 的文件。如果您像我一样好奇,在任何 XML 编辑器甚至记事本中打开它,您会发现关于映射的一切都存储在其中。您会找到关于设计图面上的所有内容的 XML 节点和元素,包括链接、Functoid、输入参数、页面、源和目标架构等。页面是当您的映射变得有点杂乱且您需要组织链接时使用的设计页面。一个好的做法是将直接链接放在一个页面中,将基于 functoid 的链接放在另一个页面中。这会更全面,一旦您的映射构建完成,它就会转换为 XSLT 文件。VS.NET 输出窗口中提供了链接,您可以打开 XSLT 文件并查看其内容。
基本上,映射用于两个目的:*消息的翻译*和*转换*。翻译仅与消息*格式*有关,而转换则与*数据*有关。换句话说,当您使用映射将消息的格式从一种转换为另一种时,您正在进行翻译。考虑将消息从平面文件格式翻译为 XML 格式。转换是使用映射在架构之间复制数据;如果您的源架构包含一个 *Salary* 数据元素,并且我们将此薪资值从人力资源部门应用程序复制到另一个部门(例如财务部门),这就是我们所说的转换。
BizTalk Server 2006 标准 Functoid
在本节中,我将简要介绍 Functoid 工具箱中包含的标准 Functoid。有些 Functoid 是不言自明的,而另一些则需要一些澄清。
Functoid 类别 | 描述 | 注释 |
字符串 | 常见的字符串操作,如修剪、提取子字符串、获取一个字符串在另一个字符串中的索引、大小写转换、连接等。 | 所有字符串操作都是基于 1 的索引。 |
数学 | +、-、*、/、%、Min、Max、Round、Square、Square Root 等。 | Round 是银行或偶数舍入;4.5 舍入到 4;所有 .5 的数字都将给出最近的偶数。 |
逻辑 | >、<、=>、<=、!=、||、&&、!、IsNil、逻辑日期、数字、字符串、存在 | 逻辑日期检查输入是否可以是日期;输入可以是字符串、数字、布尔值,它们在运行时转换为布尔值,而输出始终是布尔值。非零数字输入被视为真,而零表示假。如果输入是字符串,则比较输入是区分大小写的比较;因此 *c* 不等于 *C*。 |
日期/时间 | 日期、时间、日期和时间、添加天数 | 时间采用 24 小时制格式,添加天数采用 ISO-8601 格式的日期。 |
转换 | 八进制、十六进制、ASCII 到字符、字符到 ASCII | |
科学 | 正弦、余弦、正切、反正切、Logn、Log10、Ln、Pow、e 等。 | 三角函数使用弧度而不是角度。 |
累积 | 累积连接、求和、最小值、最大值、平均值;输入应为来自*记录*、*字段元素*或*字段属性*节点的链接。此类别中的函数用于处理重复出现的架构元素组,使用范围;默认值为 0,管理整个消息。 | 还有一个名为 *Scope* 的第二个输入参数,它决定要累积的元素;这是一个可选参数。默认值为零,累积整个消息。 |
数据库 | 包含数据库 functoid 和*交叉引用 Functoid*。数据库 functoid 包括数据库查找、值提取器、错误返回。此类别中的所有其他 functoid 都是交叉引用 Functoid。错误返回和值提取器 functoid 与数据库查找结合使用,后者从 ADO.NET 记录集中返回第一个匹配行。 | 值提取器用于从数据库查找 functoid 输出中获取列值,错误返回用于保存运行时抛出的异常消息,该消息可以写入目标架构节点。 |
高级 | 值映射、循环、表提取器、断言、迭代、索引、批量复制、脚本等。批量复制 functoid 用于复制一个元素,包括其所有或部分子元素。另一方面,条件映射类似于中间 If 或著名的 IIF。记录计数、表循环和类似的循环 functoid 用于管理不确定数量的重复元素。 | 断言用于故障排除;它确保在运行时某个值为真。此外,脚本功能也很重要,因为它在运行时调用脚本或编译代码。 |
交叉引用 Functoid:这些 Functoid 使用存储在 *BizTalkMgmtDb* 中的数据。配置向导在配置期间创建这些表。您可以在 *BizTalkMgmtDB* 数据库中找到它们。有 9 个表以 *xref_* 为前缀,但这些表在您从 9 个 XML 文件填充它们之前保持为空。这将填充数据库表,如果您不填充这些表,您将无法使用这组 Functoid。如果您尝试,您将收到异常。 BTSXRefImport.exe 是用于将数据从 XML 文档复制到数据库表的导入工具。本文将向您展示如何导入 XML 文件:导入交叉引用 Functoid 的数据。实际上,MSDN 对于设置交叉引用 Functoid 的数据库表有些不清楚,您在 MSDN 中找不到有足够解释的示例。但是,我没有将这些文件导入数据库。我稍后会尝试这样做并发布相关内容,但基本上,交叉引用用于例如当您有一个 OrderID 在不同的应用程序之间传输,并且在这些不同的应用程序中有所不同时,您可以将 ID 保存在管理数据库中,并在管理数据库中查找目标 ID。假设系统 A 中的订单状态是 OrderSent,在系统 B 中可能是 OrderSubmitted;因此您使用交叉引用来查找系统 B 的新状态值。此外,在使用导入工具之前,您需要根据 MSDN 中提供的架构填充 XML 文件。我找不到任何方法来重置这些表。在 Microsoft 增强交叉引用的文档之前,您的任何建议都将有所帮助。
Functoid 配置
如上所述,functoid 接受一些输入参数;这些参数需要配置,以告知 functoid 如何根据输入参数进行操作。在以下部分中,我们将看到一个简单的示例,该示例根据传递的 ID 从数据库中查找一些数据。我们将使用数据库查找 Functoid 和值提取器,我们还将错误返回 functoid 添加到映射中,以演示如何将这三个 functoid 一起使用。
假设您有一组商店,仅由一个总部管理,并且该总部可以向任何附属机构发送采购订单,该附属机构可以从总部指定的商店获取商品。所有通信仅在总部和附属机构之间进行,因此总部架构通过将附属机构将从中收集商品的 *StoreID* 传递给数据库查找 functoid 来查找数据库,然后提取数据以发送给附属机构。我们将首先使用值提取器 functoid 从返回的记录集中提取特定字段值,并且为了处理语法和连接失败或超时等意外错误,我们将添加一个错误返回 functoid,它将异常详细信息写入目标架构。
为简单起见,我们将使用 *Pubs* 数据库并查找 *Stores* 表。
您需要创建两个架构:*Headquarter.xsd* 和 *Affiliate.xsd*。您需要创建一个新映射并将其命名为 *Affiliate.btm*;架构和映射的详细信息显示在以下屏幕中。
现在您应该配置添加到映射中的 functoid。对于此示例,我们将配置数据库查找 functoid。您可以双击它,或者从“属性”窗口中选择输入参数。您将看到模式对话框“配置 Functoid 输入”,并且您将获得关于要添加的参数数量的良好描述。如果您尝试添加更多参数,您将无法这样做,因为一旦达到允许的输入参数数量,新的输入参数按钮将变为禁用状态。
第一个参数是从源架构中提取查找值的表达式,它由映射器构建。第二个是数据库连接字符串,强烈建议使用 Windows 集成安全性。第三个是表名,第四个是列名。您可以轻松配置其余的 functoid。值提取器 functoid 只会获取列名,它将从数据库查找 functoid 中提取一个列的值。
构建架构、映射后,您需要构建一个输入文件以提供给附属机构映射进行测试。我们将构建一个简单的 XML 文件并将其命名为 *Headquarter.xml*,这是文件的内容(包含在代码下载中)。
<ns0:Headquarter xmlns:ns0="http://FunctoidConfigurations.Headquarter">
<Store StoreID="StoreID_0" />
</ns0:Headquarter>
现在我们需要将此文件提供给映射,以便映射在测试时使用它。右键单击解决方案资源管理器中的 *Affiliate.btm* 并选择“属性”。这将打开映射属性页;选择“测试映射输入文件”并浏览到 *Headquarter.xml*。
现在您已准备好测试您的映射。右键单击解决方案资源管理器中的 Affiliate.btm 并选择“测试映射”。几秒钟后,您将在输出窗口中收到一些输出消息,并且您将获得测试映射后生成的输入和输出文件的链接;如果您打开输出文件,它应该如下所示:
<ns0:Affiliate xmlns:ns0="http://FunctoidConfigurations.Affiliate">
<Store StoreName="" Zip="">
<StoreAddress></StoreAddress>
<City></City>
<State></State>
<ErrorMessage></ErrorMessage>
</Store>
</ns0:Affiliate>
如您所见,输出为空,因为我们商店表中没有商店 ID 值“StoreID_0”。现在我们将源架构中的 StoreID 值更改为“6380”;这是商店表中存在的值。现在我们可以再次测试;这次您将获得商店 ID *6380* 的详细信息。
<ns0:Affiliate xmlns:ns0="http://FunctoidConfigurations.Affiliate">
<Store StoreName="Eric the Read Books" Zip="98056">
<StoreAddress>788 Catamaugus Ave.</StoreAddress>
<City>Seattle</City>
<State>WA</State>
<ErrorMessage></ErrorMessage>
</Store>
</ns0:Affiliate>
如您所见,数据库查找 Functoid 提取了输入商店 ID 的所有字段;如果记录集包含多个记录,则使用第一个匹配记录。
现在我们将强制数据库查找 functoid 抛出异常。只需转到数据库查找 functoid 的配置并将“X”附加到数据库表名。现在数据库表名是“storesX”。再次尝试测试映射,看看会发生什么。打开输出文件,您将得到以下 XML 输出。
<ns0:Affiliate xmlns:ns0="http://FunctoidConfigurations.Affiliate">
<Store StoreName="" Zip="">
<StoreAddress></StoreAddress>
<City></City>
<State></State>
<ErrorMessage>Invalid object name 'storesX'.</ErrorMessage>
</Store>
</ns0:Affiliate>
由于表名无效,您将无法将任何数据获取到目标架构中,并且您将收到一条有意义的错误消息,解释了获取不到数据的原因,因此建议使用错误返回 Functoid!
自定义 Functoid 架构
我们已经完成了标准 functoid,现在我们将进入 functoid 的另一个阶段:构建一个自定义 functoid。基本上,当您找不到满足您需求的标准 functoid 时,您会选择此解决方案。
我们将要构建的 Functoid 是一个货币转换器 Functoid,这里我们首先应该看看 Functoid 应该做什么和不应该做什么,以及何时使用它和不使用它。实际上,这在技术专家中一直是一个架构争议。有些人说映射只是关于映射,不应该在映射中进行业务处理,所有数据处理都应该在业务流程中进行,而另一些人则鼓励并支持在映射级别处理数据,他们的证据是 Functoid 组中包含的标准数据库 Functoid。然而,您应该决定何时使用自定义 Functoid 以及它是否会严重影响性能。这纯粹是设计和性能问题,但对于这个货币转换器 Functoid,我认为它很有用,并且将此功能封装在一个可重用的 Functoid 中是正确的。对于上面的示例,我们可以将商店货币发送给附属机构,以及当地货币兑美元的汇率,假设商店分布在全球各地。这正是我们自定义货币转换器 Functoid 的重要性所在!实际上,我见过许多需要货币转换的 EAI 解决方案。
Functoid 只是 .NET 编译代码,当然包含在一个或多个程序集中。自定义 functoid 应该继承自 `Microsoft.BizTalk.BaseFunctoids` 命名空间中包含的 `BaseFunctoid` 类。此命名空间映射到安装文件夹下的 *Developer Tools* 文件夹中的程序集 *Microsoft.BizTalk.BaseFunctoids.dll*。要创建自定义 functoid,我们将重写基类中的一些可重写方法。
自定义 Functoid 设计
让我们检查一下我们在上面的数据库查找 Functoid 中所做的操作。要了解我们需要创建货币转换器自定义 Functoid 所需的内容,在将 Functoid 拖到设计图面之前,您首先要找到您的 Functoid 所属的**类别**,然后找到您的**Functoid 名称**,前面带有一个**16x16 位图**。一旦您将鼠标移到它上面,您会看到一个**工具提示**。您需要为您的 Functoid 提供一个**描述**。您还需要提供一个**ID**,建议大于 6000(根据 Microsoft 建议)。描述非常重要,我强烈建议您尽可能详细阐述。我尝试提供与标准 Functoid 描述类似的描述。
一旦您将 functoid 放置到设计图面中,用户将开始提供输入链接,因此我们需要定义输入参数的**最小**和**最大**数量。Functoid 接受指定类型的输入参数并输出到指定类型的架构元素,因此我们还需要定义可接受的**输入连接类型**和**输出连接类型**。在运行时,映射器会调用您的 functoid,因此您应该为映射器提供一个识别您的 functoid 的名称,这对于计划部署到 GAC 的 functoid 是强制性的。您通过调用 `SetExternalFunctoinName` 来分配此名称,这为您的自定义 functoid 设置了一个**外部名称**。
那是封装 Functoid 作为组件的类,但对于实现,我们需要引用将提供货币转换的 Web 服务。此外,我们还需要构建一个资源文件来保存 Functoid 所需的字符串和位图。
您可以在货币转换器处查看 Web 服务。我们将为此 Web 服务添加 Web 引用。WSDL 契约可在货币转换器 WSDL处获得。由于我们将把 Functoid 部署到 GAC 中,我们需要为其提供一个强名称密钥文件,或者为了对我们的程序集进行数字签名,我们需要创建一个 SNK 文件,我们将在下一节中讨论。
货币转换器 Functoid 开发
在本节中,我们将构建我们的 functoid,编写代码,绘制位图,构建资源文件,并创建一个新的 SNK 文件;本节类似于一个演练。
创建一个新的类库项目,并将其命名为 *BusinessFunctoids*。将默认类文件重命名为 *CurrencyConverter.cs*。首先,我们将添加开发 functoid 所需的所有常规 Web 引用。
添加所需引用
如前所述,我们的类将继承自 `BaseFunctoid` 类。此类属于 *Microsoft.BizTalk.BaseFunctoids.dll* 程序集。您可以在 *C:\Program Files\Microsoft BizTalk Server 2006\Developer Tools* 中找到它,或者它应该位于 *Developer Tools* 安装文件夹下。您可以通过右键单击解决方案资源管理器中的“引用”并添加对该程序集的引用来添加对该程序集的引用,这样您就可以使用 `BaseFunctoid` 类。
要使用 CurrencyConverter Web 服务,您需要向您的项目添加一个 Web 引用;您可以通过右键单击您的 *BusinessFunctoids* 类库项目并选择 *添加 Web 引用* 来完成此操作。这将弹出“添加 Web 引用”窗口;您应该输入 CurrencyConverter Web 服务的 URI,即 http://www.webservicex.net/CurrencyConvertor.asmx?WSDL。现在您已准备好开始开发您的自定义 functoid。
创建强名称密钥文件
为了将我们的货币转换器 Functoid 部署到 GAC,我们需要对程序集进行数字签名,以使其在整个系统中公开;然而,在 VS.NET 2003 中,您必须从 Visual Studio .NET 工具运行 Visual Studio 命令提示符,并且可以使用 *sn* 命令;这在 VS.NET 2005 中仍然有效。要创建一个新的 *snk* 文件,打开 VS.NET 命令提示符并输入
sn -k BusinessFunctoids.snk
这将在您运行命令的位置创建 *snk* 文件;如果您在 *C:\* 并运行命令,文件将写入 C 盘。现在您需要将 *snk* 文件公开给类库项目;右键单击解决方案资源管理器中的 BusinessFunctoids 项目,选择“属性”,从左侧面板选择“签名”选项卡,选中“为程序集签名”;从下拉列表中,您可以浏览并选择使用上述命令创建的文件,或者您可以选择“新建”以直接从 VS.NET 2005 创建一个新的 SNK 文件并将其直接关联到项目——后一种方式更优雅。
构建程序集资源文件
为了向货币转换器 functoid 提供资源,我们需要创建一个新的资源文件,该文件将保存货币转换器 functoid 所需的所有字符串,以及 functoid 的 16x16 位图图标。VS.NET 资源设计器的一个奇怪之处在于它只支持字符串操作,如果您想向资源文件添加图片,它将不允许您这样做,所以我经常使用外部工具将位图添加到 *resx* 文件中,例如 Resource Editor.NET,这是 CodeProject 社区成员提供的另一个令人惊叹的工具!打开 *resx* 文件并提供这些值,然后将 *currencyicon.bmp* 添加到 *resx* 文件中。描述详细说明了 functoid 的所有内容,需要多少个参数,以及对参数的解释。
名称 | 值 |
IDS_CURRENCYFUNCTOID_DESCRIPTION |
使用货币转换器 Functoid 将字段值从一种源货币转换为另一种外币。有三个输入参数:fromCurrency、toCurrency、input field;输入货币应采用 ISO 代码格式。 |
IDS_CURRENCYFUNCTOID_NAME |
货币转换器 |
IDS_CURRENCYFUNCTOID_TOOLTIP |
货币转换器 |
IDI_CURRENCYFUNCTOID_ICON |
从 Resource Editor.NET 中选择 *currencyicon.bmp* |
CurrencyConverter Functoid 实现
在本节中,我们将为 functoid 编写代码。我们的代码分为两部分:首先是 functoid 构造函数,它调用基构造函数,其目的是向映射器工具箱定义 functoid。让我们检查构造函数代码。
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using Microsoft.BizTalk.BaseFunctoids;
5 using System.Reflection;
6 using System.Globalization;
7 using BusinessFunctoids.net.webservicex.www;
8
9 namespace BusinessFunctoids
10 {
11 ///<summary>
12 /// CurrencyConverter inherits BaseFunctoid
13 ///</summary>
14 publicclassCurrencyConverter : BaseFunctoid
15 {
16 ///<summary>
17 /// This is the defualt constructor that conveys to the toolbox.
18 ///</summary>
19 public CurrencyConverter()
20 : base()
21 {
22 this.ID = 6500;
23 // this to get the resources embedded in the resx file,
//and we call GetExecutingAssembly because
24 // the resource is compiled and embedded into the DLL.
25 SetupResourceAssembly("BusinessFunctoids.BusinessFunctoidResources",
Assembly.GetExecutingAssembly());
26
27 // Setting the functoid with resources inside resx file
28 SetTooltip("IDS_CURRENCYFUNCTOID_TOOLTIP");
29 SetBitmap("IDI_CURRENCYFUNCTOID_ICON");
30 SetName("IDS_CURRENCYFUNCTOID_NAME");
31 SetDescription("IDS_CURRENCYFUNCTOID_DESCRIPTION");
32
33 // Accepts 3 Params, source currency, destination currency, price.
34 this.SetMinParams(3);
35 this.SetMaxParams(3);
36
37 // this method call lets the mapper what function to call, when functoid
38 // is deployed to GAC, ConvertCurrencyField is the method we'll include later.
39 SetExternalFunctionName(GetType().Assembly.FullName,
"BusinessFunctoids.CurrencyConverter", "ConvertCurrencyField");
40
41 // defining category in toolbox,
//this decides under which category the functoid will be added.
42 this.Category = FunctoidCategory.Conversion;
43
44 //define output and input connection types..
45 this.OutputConnectionType = ConnectionType.AllExceptRecord;
46 AddInputConnectionType(ConnectionType.AllExceptRecord);
47
48 }
代码不言自明。在第 22 行,您为我们的 functoid 提供 ID。28-31 行设置工具箱所需的资源。34-35 行决定 functoid 有效的参数数量。39 行设置外部函数名称,42 行分配 functoid 将出现的类别,45-46 行设置输出和输入连接类型。
第 25 行调用接受两个参数的 `SetupResourceAssembly` 基方法:资源文件名和程序集。
以下部分演示了具体的 functoid 逻辑,该逻辑使用 CurrencyConverter Web 服务将输入字段从一种货币转换为另一种货币。
50 public string ConvertCurrencyField(string fromCurrency,
string toCurrency, string field)
51 {
52 decimal numericField,result = 0m;
53 double rate;
54
55 if (IsNumeric(field))
56 {
57 try
58 {
59 numericField =
Convert.ToDecimal(field, System.Globalization.CultureInfo.InvariantCulture);
60 BusinessFunctoids.net.webservicex.www.CurrencyConvertor ws_Converter;
61 ws_Converter =
new BusinessFunctoids.net.webservicex.www.CurrencyConvertor();
62
63 rate = ws_Converter.ConversionRate(
64 (BusinessFunctoids.net.webservicex.www.Currency)
Enum.Parse(typeof(BusinessFunctoids.net.webservicex.www.Currency),
fromCurrency),
65 (BusinessFunctoids.net.webservicex.www.Currency)
Enum.Parse(typeof(BusinessFunctoids.net.webservicex.www.Currency),
toCurrency)
66 );
67
68 result = Convert.ToDecimal(rate) * numericField;
69
70 }
71 catch (Exception ex)
72 {
73 throw ex;
74 }
75 }
76 return result.ToString();
77 }
上述方法是核心方法;它是将处理所有内容的 functoid。它旨在接受三个参数:fromCurrency、toCurrenty 和 field。field 是要转换的金额或数字,您应该考虑到就映射器而言,所有内容都是字符串。这就是我们向 functoid 传递字符串的原因。映射器不操纵数据类型转换;此外,参数和返回值都应该是字符串。该函数应该是公共的,以允许映射器调用它;在函数内部,您应该检查输入参数的数据类型,这更像是一种数据类型验证,因为架构根据架构定义验证输入值。
代码不言自明,您应该从 WSDL 和 Web 服务网站提供的示例中了解到,它期望货币采用 ISO 格式,并且有一个货币枚举器,其中包含所有支持的货币。最好将代码放在 `try-catch` 块之间,因为我们正在调用外部 Web 服务。第 63-66 行调用 Web 服务,传递枚举的货币代码。然后我们得到汇率,这是我们最需要的重要值。第 68-69 行根据汇率值计算目标货币中的字段,然后我们将值转换为字符串后返回。
恭喜!您已完成货币转换器 Functoid 的开发,剩余部分将重点介绍 Functoid 的部署和测试。
将货币转换器 Functoid 添加到工具箱
当映射器启动时,它会检查一个特定文件夹并加载该文件夹中的任何 functoid 程序集。此文件夹是 Developer Tools 文件夹下的 Mapper Extensions 文件夹。您需要将您的 functoid 程序集 *BusinessFunctoids.dll* 复制到此文件夹。现在您可以将货币转换器 functoid 添加到 VS.NET functoid 工具箱中。在 VS.NET 中打开一个映射以获取 Functoid 工具箱,然后从“工具”菜单中,选择“选择工具箱项”,选择“Functoid”选项卡,然后浏览到您之前复制 *BusinessFunctoids.dll* 的 Mapper Extensions 文件夹。选择 BusinessFunctoids 并按“确定”。您将在窗口的下半部分看到 CurrencyConverter functoid 的图标,单击“确定”,焦点将转到“转换”类别下的 Currency Converter functoid。
在 GAC 中注册货币转换器 Functoid
货币转换器是一个全局 functoid,它将被映射器调用,因此我们需要使用 VS.NET 2005 命令提示符将其部署到全局程序集缓存中。打开 VS.NET 2005 命令提示符并浏览到 Mapper Extensions 文件夹,然后输入以下内容以将货币转换器 functoid 注册到全局程序集缓存中。
gacutil /if BusinessFunctoids.dll
如果过程顺利,您将收到“程序集已成功添加到缓存”的消息;如果您想确认程序集已添加到 GAC,请浏览到 Windows 安装目录,然后到程序集目录,并尝试找到 BusinessFunctoids 程序集;如果它在那里,一切都很好,并且程序集已物理安装在 GAC 中。
货币转换器 Functoid 使用
现在是使用货币转换器 functoid 的时候了。我们将创建两个架构和一个映射。假设出口商向外国进口商销售产品,并且出口商应该以外国进口商的货币发送价格。为此,您需要创建一个新的空 BizTalk Server 项目,将其命名为 *CurrencyFunctoid*,并添加一个新的架构文件,将其命名为 *ExporterSchema.xsd*,并将根节点重命名为 *ExporterOrder*。右键单击此节点并选择 *插入架构节点 -> 子记录*。将其重命名为 *Order* 并将 *Min Occurs* 和 *Max Occurs* 属性设置为 *1*。右键单击 Order 节点并选择 *插入架构节点 -> 子记录*,将其重命名为 *Item* 并将 *Min Occurs* 设置为 *1*,将 *Max Occurs* 设置为 *(无限制),然后将以下字段添加到 Item 记录中。
字段 | 名称 | DataType |
Attribute | currency |
xs:string |
Attribute | foreignCurrency |
xs:string |
元素 | price |
xs:decimal |
元素 | quantity |
xs:unsignedInt |
元素 | productCode |
xs:string |
向项目添加一个新的架构文件,命名为 *ImporterSchema.xsd*,将根节点重命名为 *Order*,右键单击此节点,然后选择 *插入架构节点 -> 子记录*,将其重命名为 *Item*,并将 *Min Occurs* 设置为 *1*,将 *Max Occurs* 设置为 *(无限制)。将以下字段添加到 Item 记录中。
字段 | 名称 | DataType |
Attribute | PId |
xs:string |
Attribute | quantity |
xs:unsignedInt |
元素 | price |
xs:decimal |
为项目创建一个新映射,并将其命名为 *CurrencyConversion.btm*。将源架构设置为 ExporterSchema,目标架构设置为 ImporterSchema;从 productCode 到 PId,以及从 quantity 到 quantity 创建直接链接,然后从工具箱中拖动货币转换器 functoid,它应该位于“转换”类别下。一旦您将其放置在设计图面上,您可以通过双击它或单击“属性”窗口中“Functoid 输入”旁边的省略号按钮来配置 functoid 输入。在配置窗口中,您只能输入三个参数。此外,您将看到之前在资源文件中输入的 functoid 描述标签中的描述。不添加任何参数关闭窗口,然后将 currency、foreignCurrency 和 price 节点分别拖到 Currency Converter Functoid 中。这些将作为 Currency Converter Functoid 的输入参数。双击 functoid,它应该如下所示:
转到设计图面,将链接从货币转换器 functoid 拖动到目标 ImporterSchema 中的价格元素;这将把结果写入此元素。创建映射后,它就可以进行测试了。为了进行测试,我们将使用代码下载中提供的 *Map_test_Input.xml*。这是输入 XML 消息的内容。
<ns0:ExporterOrder xmlns:ns0="http://CurrencyFunctoid.ExporterSchema">
<Order>
<Item currency="USD" foreignCurrency="EGP">
<price>10.4</price>
<quantity>10</quantity>
<productCode>productCode_0</productCode>
</Item>
</Order>
</ns0:ExporterOrder>
输入货币是美元,目标货币是埃及镑。假设出口商在美国,进口商在埃及;要将此输入测试文件提供给映射,右键单击解决方案资源管理器中的 *CurrencyConversion.btm*,选择“属性”,选择“测试映射输入实例”,然后单击省略号按钮并浏览到 *Map_test_Input.xml*。单击“打开”,然后单击“确定”。右键单击解决方案资源管理器中的 *CurrencyConversion.btm* 映射并选择“测试映射”。将显示输出窗口,测试映射后,您将在输出窗口中获得一个输出文件的链接。按 CTRL+单击以在 VS.NET 中打开它。您将获得以下输出消息。
<ns0:Order xmlns:ns0="http://CurrencyFunctoid.ImporterSchema">
<Item PId="productCode_0">
<quantity>10</quantity>
<price>59.7272</price>
</Item>
</ns0:Order>
恭喜,价格以外币列出;如果您将 59.7272 除以 10.4,您将得到 5.743,这是美元兑埃及镑的汇率。
使用代码
代码下载包含一个名为 CurrencyFunctoid 的解决方案,以及三个项目:包含 CurrencyConverter functoid 的类库 BusinessFunctoids,用作自定义 CurrencyConverter functoid 测试应用程序的 CurrencyFunctoid,以及我们上面看到的数据库查找 functoid 示例 FunctoidConfigurations。
兴趣点
对于我们的货币转换器 functoid,我们只考虑了应该部署到 GAC 的 GAC functoid;但是,我们还有另一个选项可以构建一个名为内联脚本 functoid 的 functoid。在这种方法中,您将您的 functoid 代码(即 .NET 代码)公开给映射器,在运行时,映射器将 functoid 代码嵌入到映射中。虽然这具有独立于 GAC 程序集的优点,但它也有您需要将代码嵌入到映射中的缺点。
货币转换器 Functoid 依赖于货币转换器 Web 服务;如果接口发生变化(这种情况很少见),您应该注意这一点。
结论
在本文中,您学习了如何使用标准 functoid,我们还通过一个示例了解了如何使用数据库查找 functoid。此外,我们构建了一个 GAC 货币转换器自定义 functoid,该 functoid 使用货币转换器 Web 服务。