您的位置:首页 > 移动开发 > Objective-C

Inside ObjectBuilder Part 4

2007-12-18 21:39 309 查看
  ObjectBuilderApplicationBlock
/黄忠成

2006/9/21
 
八、ObjectBuilder实务
 
8-1ObjectBuilderWithConfiguration截至目前为止,本文一直以程序方式来配置ObjectBuidler建立对象所需的各种对象,但在实务上,这些动作应该是交由配置文件来负责,这样才能在不重新编译应用程序的情况下,改变其行为或增加其功能。很幸运的,Microsoft于ObjectBuilder的范例中提供了一个途径来达到此目的,该范例定义了一个.xsd文件,其内定义了ConstructorInjection、SetterInjection、Singleton、TypeMapping所需要的schema,当然!这个xsd中也定义了Strategy的schema,允许设计者通过配置文件来添加对象建立时所需使用的Strategys。

 
ConsturctorInjectionWithConfiguration我将Microsoft所提供可配置ObjectBuidler的范例中关于处理配置文件时的.xsd及相关文件提取出来,并添加MethodInjection时所需要的schema及程序代码,放置于本文的范例程序档中,当读者们需要使用配置文件这个功能时,可以将Config目录中的ObjectBuilderXmlConfig.xsd、ObjectBuilderXmlConfig.xsx、ObjectBuilderXmlConfig.cs、ObjectBuilderXmlConfig.Generate.cs等文件复制到项目目录中,并将ObjectBuilderXmlConfig.xsd、ObjectBuilderXmlConfig.Generate.cs加入到项目中,完成后再将ObjectBuilderXmlConfig.xsd设置成EmbeddedResource,如图10所示。
图10

接着将修改ObjectBuilderXmlConfig.cs中关于由Resource中取得.xsd内容的程序代码,修正namespace为项目的默认namespace即可。
程序44

privatestaticObjectBuilderXmlConfigParseXmlConfiguration(stringconfig)
{
XmlSerializerser=newXmlSerializer(typeof(ObjectBuilderXmlConfig));
StringReaderstringReader=newStringReader(config);
XmlSchemaschema=
XmlSchema.Read(
Assembly.GetExecutingAssembly().GetManifestResourceStream(
"OB_CSConfigurationTest.ObjectBuilderXmlConfig.xsd"),null);
XmlReaderSettingssettings=newXmlReaderSettings();
settings.ValidationType=ValidationType.Schema;
settings.Schemas.Add(schema);
XmlReaderreader=XmlReader.Create(stringReader,settings);
ObjectBuilderXmlConfigconfigData=(ObjectBuilderXmlConfig)ser.Deserialize(reader);
returnconfigData;
}
 要使用配置文件来完成ConstructorInjection,我们必须在项目中新增一个xml文件,内容如下所示。

 

<object-builder-configxmlns="pag-object-builder">
<build-rules>
<build-rule
type="OB_ConfigurationTest.InputAccept,OB_CSConfigurationTest"mode="Instance">
<constructor-params>
<ref-param
type="OB_ConfigurationTest.PromptDataProcessor,OB_CSConfigurationTest"/>
constructor-params>
build-rule>
build-rules>
object-builder-config>
 在ObjectBuilderXmlConfig.xsd定义中,build-rules代表着此BuilderContext中所有的对象建立规则,每个build-rule对应着一个“类型/id”,类型格式为,id
20bbb
部份则可通过添加name这个attribute来设置,未指定时就以null为默认值,如下。

 

<build-rule
type="OB_ConfigurationTest.InputAccept,OB_CSConfigurationTest"
name=”id1”mode="Instance">
 每个build-rule可以拥有一个constructor-params区段,设计者可以在这个区段中添加value-param或是ref-param定义,前者是直接设置该参数的值,后者是通过reference方式来设值,本例中是将InputAccept建构子的第一个参数值指定为PromptDataProcessor。程序45是使用这个配置文件的程序列表。

 程序45

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.IO;
usingSystem.Configuration;
usingMicrosoft.Practices.ObjectBuilder;
usingMicrosoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
usingMicrosoft.Practices.EnterpriseLibrary.Common.Configuration;
 
namespaceOB_ConfigurationTest
{
classProgram
{
staticvoidMain(string[]args)
{
using(FileStreamfs=newFileStream("XmlFile1.xml",FileMode.Open,FileAccess.Read))
{
using(StreamReadersr=newStreamReader(fs))
{
Builderbuilder=newBuilder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAcceptaccept=builder.BuildUp<InputAccept>(newLocator(),null,null);
accept.Execute();
Console.Read();
}
}
}
}
 
publicclassInputAccept
{
privateIDataProcessor_dataProcessor;
 
publicvoidExecute()
{
Console.Write("PleaseInputsomewords:");
stringinput=Console.ReadLine();
input=_dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
 
publicInputAccept([Dependency(Name="dataProcessor")]IDataProcessordataProcessor)
{
_dataProcessor=dataProcessor;
}
}
 
publicinterfaceIDataProcessor
{
stringProcessData(stringinput);
}
 
publicclassDummyDataProcessor:IDataProcessor
{
 
#regionIDataProcessorMembers
 
publicstringProcessData(stringinput)
{
returninput;
}
 
#endregion
}
 
publicclassPromptDataProcessor:IDataProcessor
{
#regionIDataProcessorMembers
 
publicstringProcessData(stringinput)
{
return"yourinputis:"+input;
}
 
#endregion
}
}
 SetterInjectionWithConfiguration

 同样的,我们也可以通过配置文件来完成SetterInjection,此范例所使用的配置文件如下。

 

<object-builder-configxmlns="pag-object-builder">
<build-rules>
<build-rule
type="OB_CSPropertyInjectionTest.InputAccept,OB_CSPropertyInjectionTest"mode="Instance">
<propertyname="DataProcessor">
<ref-param
type="OB_CSPropertyInjectionTest.PromptDataProcessor,OB_CSPropertyInjectionTest"/>
property>
build-rule>
build-rules>
object-builder-config>
 设计者必须将要设置的属性定义放置于build-rule区段中的property,property有一个nameattribute,代表着欲设置属性的名称,如要设置一个以上的属性,只需添加多个property区段即可,程序46是使用此配置文件的程序代码。

 程序46

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.IO;
usingSystem.Configuration;
usingMicrosoft.Practices.ObjectBuilder;
usingMicrosoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
usingMicrosoft.Practices.EnterpriseLibrary.Common.Configuration;
 
namespaceOB_CSPropertyInjectionTest
{
classProgram
{
staticvoidMain(string[]args)
{
using(FileStreamfs=newFileStream("XmlFile1.xml",FileMode.Open,FileAccess.Read))
{
using(StreamReadersr=newStreamReader(fs))
{
Builderbuilder=newBuilder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAcceptaccept=builder.BuildUp<InputAccept>(newLocator(),null,null);
accept.Execute();
Console.Read();
}
}
}
}
 
publicclassInputAccept
{
privateIDataProcessor_dataProcessor;
 
[Dependency(Name="DataProcessor")]
publicIDataProcessorDataProcessor
{
get
{
return_dataProcessor;
}
set
{
_dataProcessor=value;
}
}
 
publicvoidExecute()
{
Console.Write("PleaseInputsomewords:");
stringinput=Console.ReadLine();
input=_dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
 
publicinterfaceIDataProcessor
{
stringProcessData(stringinput);
}
 
publicclassDummyDataProcessor:IDataProcessor
{
 
#regionIDataProcessorMembers
 
publicstringProcessData(stringinput)
{
returninput;
}
 
#endregion
}
 
publicclassPromptDataProcessor:IDataProcessor
{
#regionIDataProcessorMembers
 
publicstringProcessData(stringinput)
{
return"yourinputis:"+input;
}
 
#endregion
}
}
 MethodInjectionWithConfiguration

 Microsoft所提供的配置文件机制并未定义MethodInjection的功能,我将其稍微修改来支援此功能,下面是MethodInjection时所用的配置文件。

 

<object-builder-configxmlns="pag-object-builder">
<build-rules>
<build-rule
type="OB_CSMethodInjectionTest.InputAccept,OB_CSMethodInjectionTest"mode="Instance">
<methodname="SetDataProcessor">
<ref-param
type="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest"/>
method>
build-rule>
build-rules>
object-builder-config>
 用法与property大致相同,程序47是程序代码列表。

 程序47

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.IO;
usingMicrosoft.Practices.ObjectBuilder;
 
namespaceOB_CSMethodInjectionTest
{
classProgram
{
staticvoidMain(string[]args)
{
using(FileStreamfs=newFileStream("XmlFile1.xml",FileMode.Open,FileAccess.Read))
{
using(StreamReadersr=newStreamReader(fs))
{
Builderbuilder=newBuilder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAcceptaccept=builder.BuildUp<InputAccept>(newLocator(),null,null);
accept.Execute();
Console.Read();
}
}
}
}
 
publicclassInputAccept
{
privateIDataProcessor_dataProcessor;
 
publicvoidSetDataProcessor([Dependency(Name="dataProcessor")]IDataProcessordataProcessor)
{
_dataProcessor=dataProcessor;
}
 
publicvoidExecute()
{
Console.Write("PleaseInputsomewords:");
stringinput=Console.ReadLine();
input=_dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
 
publicinterfaceIDataProcessor
{
stringProcessData(stringinput);
}
 
publicclassDummyDataProcessor:IDataProcessor
{
 
#regionIDataProcessorMembers
 
publicstringProcessData(stringinput)
{
returninput;
}
 
#endregion
}
 
publicclassPromptDataProcessor:IDataProcessor
{
#regionIDataProcessorMembers
 
publicstringProcessData(stringinput)
{
return"yourinputis:"+input;
}
 
#endregion
}
}
 SingletonWithConfiguration

 通过配置文件,也可以定义那个“类型/id”的对象是使用Singleton模式,如下所示。

 

<build-ruletype="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest"mode="Singleton"/>
 TypeMappingWithConfiguration

 我们也可以在配置文件中定义TypeMapping,如下所示。

 

<build-rule
type="OB_CSMethodInjectionTest.IDataProcessor,OB_CSMethodInjectionTest"mode="Instance">
<mapped-type
type="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest"/>
build-rule>
 CustomizeStrategys

 通过配置文件,也可以定义建立对象时所需要的Strategys,如下所示。

 

<object-builder-configxmlns="pag-object-builder">
<strategiesinclude-default="false">
<strategy
type="Microsoft.Practices.ObjectBuilder.TypeMappingStrategy,Microsoft.Practices.ObjectBuilder"/>
<strategy
type="Microsoft.Practices.ObjectBuilder.CreationStrategy,Microsoft.Practices.ObjectBuilder"/>
<strategy
type="Microsoft.Practices.ObjectBuilder.MethodExecutionStrategy,Microsoft.Practices.ObjectBuilder"/>
.......................
object-builder-config>
 include-default属性决定是否包含Builder对象所内建的Strategys。

 九、后记
ObjectBuilder是一个相当不错的DependencyInjection实作体,虽然相对于Spring、Avalon,ObjectBuilder并不是相当的完整,例如没有完整的配置文件驱动特色,但她所具备的高度延展性,可以让我们轻易的达到这个需求,且日后相信ObjectBuilder也会内建这些功能的。

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1282167
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息