可以定制三种类型的pipeline component:general, assembling,disassembling。
其中disassembling是接收管道的Disassemble阶段使用的pipeline component类型,assembling是发送管道Assemble阶段使用的pipeline component类型,两种管道的其它阶段都是用general类型的pipeline component。
pipeline component是.net或com的组件,用来实现不同阶段的管道任务,根据不同类型的pipeline component类型需要实现一些接口以便消息引擎调用来传送和返回相关信息。
传递组件所在管道的上下文,当前所在管道的stage等
组件可以获得消息和消息工厂
这个接口对象是作为参数传入到组件,给组件内部的代码使用,不需要哪个pipeline component去实现这个接口。
组件通过这个接口提供这个组件的基本信息:名称、版本、描述
General类型的pipeline component必须实现的接口。General类型一般接收一个消息,处理消息,然后返回一个消息。
需要实现方法:
l IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
消息引擎调用此方法把消息传入pipeline component,返回pipeline component处理后的消息。
IpersistPropertyBag 接口用来作为环境(开发环境、biztalk控制台等)跟pipeline component的运行时属性交互时,作为设计时属性提供的一组功能。提供设计时环境设置和获得pipeline component属性的功能。
IpersistPropertyBag 接口有两个主要方法:
l void Load(IPropertyBag propertyBag, int errorLog);
环境调用此方法装载所有在环境中保存的pipeline componen属性值。就是在把在开发环境或者biztalk控制台中设置的pipeline componen相关属性值传递给pipeline componen本身。
l void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties);
环境调用此方法把pipeline componen属性值取出来,保存到开发环境或者biztalk控制台的pipeline componen相关属性。
IpropertyBag接口是IpersistPropertyBag接口的两个方法提供的参数类型,不需要pipeline componen实现这个接口。
实际上这个接口就是把pipeline component属性暴露给环境,使用者可以在开发环境或biztalk控制台中随时修改这些暴露的属性,给配置pipeline提供了很大的灵活性。
例如,pipeline componen定义了一个叫Filter的属性:
private string filter = null;
[System.ComponentModel.Description("属性描述")]
public string Filter
{
get { return filter; }
set { filter = value; }
}
如果这个pipeline componen没有实现IpersistPropertyBag接口,组件的Filter属性在环境中能看到,但是在环境中设置了这个属性值在运行时将不会被传送到组件。
看一下如何实现这个接口的两个主要方法:
void IPersistPropertyBag.Load(IPropertyBag propertyBag, int errorLog)
{
object objSheetName = null;
try
{
propertyBag.Read("SheetName", out objSheetName, 0);
}
catch (ArgumentException argEx)
{
//throw argEx;
}
catch (Exception ex)
{
throw new ApplicationException("从propertybag读取属性出错: " + ex.Message);
}
if (objSheetName != null)
SheetName = (string)objSheetName;
else
SheetName = "";
}
void IPersistPropertyBag.Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)
{
object objFilter = (object)Filter;
propertyBag.Write("Filter", ref objFilter);
}
Disassembling类型的pipeline component必须要实现这个接口,这类组件接收一个消息,生成0个或者多个消息返回。
此接口需要实现两个方法:
l void Disassemble(IPipelineContext pContext, IBaseMessage pInMsg)
消息引擎调用此方法把需要处理的消息传送给此pipeline component
l IBaseMessage GetNext(IPipelineContext pContext)
pipeline component处理消息获得0个或多个消息,通过此方法获得下一个消息,直到返回NULL表示没有下一个消息了。
Assembling 类型的pipeline component必须要实现这个接口,这类组件接收多个消息集合起来形成一个消息交换(message interchange)中,但是在biztalk2006版本中并没有实现这个功能,所以消息引擎总是只发送一个消息进入此类pipeline component。
此接口需要实现两个方法:
l void AddDocument(IPipelineContext pContext, IBaseMessage pInMsg);
往要形成消息交换的集合中增加一个消息(biztalk2006版本中只会调用一次此方法)。
l IBaseMessage Assemble(IPipelineContext pContext);
把上面方法接收到的所有消息集合形成一个消息交换(message interchange)返回。
用来探测输入的消息是否本pipeline component所认识的消息类型。
需要实现以下方法:
l bool Probe(IPipelineContext pContext, IBaseMessage pInMsg);
如果输入的消息是本pipeline component所认识的返回true,否则返回false
为了在设计环境中使用pipeline component,所有的pipeline component都必须实现这个接口。
必须实现以下属性:
l IntPtr Icon { get; }
获得此组件的设计时图标
l IEnumerator Validate(object projectSystem);
管道设计器在编译前调用此方法,以检验所有的设置属性都是正确的。
各类型pipeline component实现接口
General | disassembling | assembling | |
IBaseComponent | √ | √ | √ |
IComponent | √ | X | X |
IPersistPropertyBag | ○ | ○ | ○ |
IDisassemblerComponent | X | √ | X |
IAssemblerComponent | X | X | √ |
IProbeMessage | ○ | ○ | ○ |
IComponentUI | ○ | ○ | ○ |
在实现IpersistPropertyBag接口的Load方法时,使用IpropertyBag的Read方法读取环境的属性值时,一定要使用try/catch结构捕获ArgumentException异常,不然在把这个管道组件拖放到管道的pipeline stage时,会产生"pipeline component load() method failed on IPersisPropertyBag implementation"错误。因为在把管道组件拖放到pipeline stage时,开发环境首先调用IpersistPropertyBag接口的Load方法把开发环境的设计时属性值写入到管道组件本身的属性,而这时设计时属性也都是null的,读取设计时属性时就会抛出ArgumentException异常。
开发环境修改了设计时属性后,保存pipeline时,调用IpersistPropertyBag接口的Load方法把设计时属性值写入到管道组件本身的属性。
在开发环境中打开一个pipeline时,调用IpersistPropertyBag接口的Save方法,把管道组件本身的属性读入到设计时属性。
在IpersistPropertyBag接口的Load和Save方法中保存、装载的属性,也就是这个组件暴露在外可以灵活修改的那些属性实际上保存在管道btp文件中。
比如:
<Stage CategoryId="9d0e4103-4cce-4536-83fa-4a5040674ad6">
<Components>
<Component>
<Name>ExcelPipelineComponent.ExcelComponent</Name>
<ComponentName>Excel decoder</ComponentName>
<Description>将Excel文件转换成xml的管道组件</Description>
<Version>1.0</Version>
<Properties>
<Property Name="SheetName">
<Value xsi:type="xsd:string">contact</Value>
</Property>
<Property Name="Filter">
<Value xsi:type="xsd:string" />
</Property>
<Property Name="NameSpace">
<Value xsi:type="xsd:string">http://chnking</Value>
</Property>
<Property Name="RootNode">
<Value xsi:type="xsd:string">employees</Value>
</Property>
<Property Name="HDR">
<Value xsi:type="xsd:boolean">true</Value>
</Property>
</Properties>
<CachedDisplayName>Excel decoder</CachedDisplayName>
<CachedIsManaged>true</CachedIsManaged>
</Component>
</Components>
</Stage>
上面这段btp文件中,在decoder阶段中有一个组件,这个组件有5个公开属性。这些属性会显示在这个组件的属性窗口中。使用pipeline.exe调试组件时,可以通过修改btp文件中的相应属性改变测试的不同情况。
定制管道组件经常会设计一些属性,提供灵活配置管道组件的手段,这些属性可以在开发环境的属性窗口中显示并被修改,也可以在biztalk的控制台中显示并修改。
缺省的,定制组件类的public的属性都会被显示在属性窗口中。
可以通过在属性的前面增加“[Browsable(false)]” attribute来控制属性不被显示在属性窗口,比如:
[Browsable(false)]
public string Version
{
get { return "1.0"; }
}