Inside ObjectBuilder Part 4

    技术2022-05-11  43

     

    ObjectBuilderApplicationBlock

    /黄忠成

    2006/9/21

     

    八、ObjectBuilder实务

     

    8-1ObjectBuilderWithConfiguration

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

     

    ConsturctorInjectionWithConfiguration

    我将Microsoft所提供可配置ObjectBuidler的范例中关于处理配置文件时的.xsd及相关文件提取出来,并添加MethodInjection时所需要的schema及程序代码,放置于本文的范例程序档中,当读者们需要使用配置文件这个功能时,可以将Config目录中的ObjectBuilderXmlConfig.xsdObjectBuilderXmlConfig.xsxObjectBuilderXmlConfig.csObjectBuilderXmlConfig.Generate.cs等文件复制到项目目录中,并将ObjectBuilderXmlConfig.xsdObjectBuilderXmlConfig.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部份则可通过添加name这个attribute来设置,未指定时就以null为默认值,如下。

     

    <build-rule

    type="OB_ConfigurationTest.InputAccept,OB_CSConfigurationTest"

    name=”id 1” 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区段中的propertyproperty有一个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实作体,虽然相对于SpringAvalonObjectBuilder并不是相当的完整,例如没有完整的配置文件驱动特色,但她所具备的高度延展性,可以让我们轻易的达到这个需求,且日后相信ObjectBuilder也会内建这些功能的。

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1282167


    最新回复(0)