[转]Object Builder Application Block文/黄忠成 ;2006/9/21
原文链接:http://blog.csdn.net/Code6421/archive/2006/09/25/1282167.aspx
整理:吕震宇
八、ObjectBuilder实务8-1、ObjectBuilderWithConfiguration截至目前为止,本文一直以程序方式来配置ObjectBuidler建立对象所需的各种对象,但在实务上,这些动作应该是交由配置文件来负责,这样才能在不重新编译应用程序的情况下,改变其行为或增加其功能。很幸运的,Microsoft于ObjectBuilder的范例中提供了一个途径来达到此目的,该范例定义了一个.xsd文件,其内定义了ConstructorInjection、SetterInjection、Singleton、TypeMapping所需要的schema,当然!这个xsd中也定义了Strategy的schema,允许设计者通过配置文件来添加对象建立时所需使用的Strategys。
图10

接着将修改ObjectBuilderXmlConfig.cs中关于由Resource中取得.xsd内容的程序代码,修正namespace为项目的默认namespace即可。
程序44
private static ObjectBuilderXmlConfig ParseXmlConfiguration(string config)
{
XmlSerializer ser = new XmlSerializer(typeof(ObjectBuilderXmlConfig));
StringReader stringReader = new StringReader(config);
XmlSchema schema = XmlSchema.Read(Assembly.GetExecutingAssembly().GetManifestResourceStream(
"OB_CSConfigurationTest.ObjectBuilderXmlConfig.xsd"), null);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(schema);
XmlReader reader = XmlReader.Create(stringReader, settings);
ObjectBuilderXmlConfig configData = (ObjectBuilderXmlConfig)ser.Deserialize(reader);
return configData;
}
要使用配置文件来完成ConstructorInjection,我们必须在项目中新增一个xml文件,内容如下所示。
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="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”,类型格式为<type,Assembly>,id部份则可通过添加name这个attribute来设置,未指定时就以null为默认值,如下。
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="pag-object-builder" >
<build-rules >
<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
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Configuration;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
namespace OB_ConfigurationTest
{
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("XmlFile1.xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
Builder builder = new Builder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAccept accept = builder.BuildUp<InputAccept>(new Locator(), null, null);
accept.Execute();
Console.Read();
}
}
}
}
public class InputAccept
{
private IDataProcessor _dataProcessor;
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
public InputAccept([Dependency(Name = "dataProcessor")]IDataProcessor dataProcessor)
{
_dataProcessor = dataProcessor;
}
}
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return input;
}
#endregion
}
public class PromptDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return "your input is:" + input;
}
#endregion
}
}
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="pag-object-builder" >
<build-rules >
<build-rule type="OB_CSPropertyInjectionTest.InputAccept,OB_CSPropertyInjectionTest" mode="Instance" >
<property name="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
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Configuration;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
namespace OB_CSPropertyInjectionTest
{
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("XmlFile1.xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
Builder builder = new Builder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAccept accept = builder.BuildUp<InputAccept>(new Locator(), null, null);
accept.Execute();
Console.Read();
}
}
}
}
public class InputAccept
{
private IDataProcessor _dataProcessor;
[Dependency(Name = "DataProcessor")]
public IDataProcessor DataProcessor
{
get
{
return _dataProcessor;
}
set
{
_dataProcessor = value;
}
}
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return input;
}
#endregion
}
public class PromptDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return "your input is:" + input;
}
#endregion
}
}
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="pag-object-builder" >
<build-rules >
<build-rule type="OB_CSPropertyInjectionTest.InputAccept,OB_CSPropertyInjectionTest" mode="Instance" >
<property name="DataProcessor" >
<ref-param type="OB_CSPropertyInjectionTest.PromptDataProcessor,OB_CSPropertyInjectionTest" />
</property>
</build-rule>
</build-rules>
</object-builder-config>
用法与property大致相同,程序47是程序代码列表。
程序47
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Practices.ObjectBuilder;
namespace OB_CSMethodInjectionTest
{
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("XmlFile1.xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
Builder builder = new Builder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAccept accept = builder.BuildUp<InputAccept>(new Locator(), null, null);
accept.Execute();
Console.Read();
}
}
}
}
public class InputAccept
{
private IDataProcessor _dataProcessor;
public void SetDataProcessor([Dependency(Name = "dataProcessor")]IDataProcessor dataProcessor)
{
_dataProcessor = dataProcessor;
}
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return input;
}
#endregion
}
public class PromptDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return "your input is:" + input;
}
#endregion
}
}
<build-rule type="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest" mode="Singleton" />
<build-rule type="OB_CSMethodInjectionTest.IDataProcessor,OB_CSMethodInjectionTest" mode="Instance" >
<mapped-type type="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest" />
</build-rule>
<object-builder-config xmlns="pag-object-builder" >
<strategies include-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" />
.............
</strategies>
</object-builder-config>
include-default属性决定是否包含Builder对象所内建的Strategys。
九、后记ObjectBuilder是一个相当不错的DependencyInjection实现对象,虽然相对于Spring、Avalon,ObjectBuilder并不是相当的完整,例如没有完整的配置文件驱动特色,但它所具备的高度延展性,可以让我们轻易的达到这个需求,且日后相信ObjectBuilder也会内建这些功能的。
原文链接:http://blog.csdn.net/Code6421/archive/2006/09/25/1282167.aspx
整理:吕震宇
八、ObjectBuilder实务8-1、ObjectBuilderWithConfiguration截至目前为止,本文一直以程序方式来配置ObjectBuidler建立对象所需的各种对象,但在实务上,这些动作应该是交由配置文件来负责,这样才能在不重新编译应用程序的情况下,改变其行为或增加其功能。很幸运的,Microsoft于ObjectBuilder的范例中提供了一个途径来达到此目的,该范例定义了一个.xsd文件,其内定义了ConstructorInjection、SetterInjection、Singleton、TypeMapping所需要的schema,当然!这个xsd中也定义了Strategy的schema,允许设计者通过配置文件来添加对象建立时所需使用的Strategys。
- ConsturctorInjectionWithConfiguration
图10

接着将修改ObjectBuilderXmlConfig.cs中关于由Resource中取得.xsd内容的程序代码,修正namespace为项目的默认namespace即可。
程序44
private static ObjectBuilderXmlConfig ParseXmlConfiguration(string config)
{
XmlSerializer ser = new XmlSerializer(typeof(ObjectBuilderXmlConfig));
StringReader stringReader = new StringReader(config);
XmlSchema schema = XmlSchema.Read(Assembly.GetExecutingAssembly().GetManifestResourceStream(
"OB_CSConfigurationTest.ObjectBuilderXmlConfig.xsd"), null);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(schema);
XmlReader reader = XmlReader.Create(stringReader, settings);
ObjectBuilderXmlConfig configData = (ObjectBuilderXmlConfig)ser.Deserialize(reader);
return configData;
}
要使用配置文件来完成ConstructorInjection,我们必须在项目中新增一个xml文件,内容如下所示。
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="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”,类型格式为<type,Assembly>,id部份则可通过添加name这个attribute来设置,未指定时就以null为默认值,如下。
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="pag-object-builder" >
<build-rules >
<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
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Configuration;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
namespace OB_ConfigurationTest
{
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("XmlFile1.xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
Builder builder = new Builder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAccept accept = builder.BuildUp<InputAccept>(new Locator(), null, null);
accept.Execute();
Console.Read();
}
}
}
}
public class InputAccept
{
private IDataProcessor _dataProcessor;
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
public InputAccept([Dependency(Name = "dataProcessor")]IDataProcessor dataProcessor)
{
_dataProcessor = dataProcessor;
}
}
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return input;
}
#endregion
}
public class PromptDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return "your input is:" + input;
}
#endregion
}
}
- SetterInjectionWithConfiguration
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="pag-object-builder" >
<build-rules >
<build-rule type="OB_CSPropertyInjectionTest.InputAccept,OB_CSPropertyInjectionTest" mode="Instance" >
<property name="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
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Configuration;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
namespace OB_CSPropertyInjectionTest
{
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("XmlFile1.xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
Builder builder = new Builder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAccept accept = builder.BuildUp<InputAccept>(new Locator(), null, null);
accept.Execute();
Console.Read();
}
}
}
}
public class InputAccept
{
private IDataProcessor _dataProcessor;
[Dependency(Name = "DataProcessor")]
public IDataProcessor DataProcessor
{
get
{
return _dataProcessor;
}
set
{
_dataProcessor = value;
}
}
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return input;
}
#endregion
}
public class PromptDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return "your input is:" + input;
}
#endregion
}
}
- MethodInjectionWithConfiguration
<?xml version="1.0" encoding="utf-8"?>
<object-builder-config xmlns="pag-object-builder" >
<build-rules >
<build-rule type="OB_CSPropertyInjectionTest.InputAccept,OB_CSPropertyInjectionTest" mode="Instance" >
<property name="DataProcessor" >
<ref-param type="OB_CSPropertyInjectionTest.PromptDataProcessor,OB_CSPropertyInjectionTest" />
</property>
</build-rule>
</build-rules>
</object-builder-config>
用法与property大致相同,程序47是程序代码列表。
程序47
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Practices.ObjectBuilder;
namespace OB_CSMethodInjectionTest
{
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("XmlFile1.xml", FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
Builder builder = new Builder(ObjectBuilderXmlConfig.FromXml(sr.ReadToEnd()));
InputAccept accept = builder.BuildUp<InputAccept>(new Locator(), null, null);
accept.Execute();
Console.Read();
}
}
}
}
public class InputAccept
{
private IDataProcessor _dataProcessor;
public void SetDataProcessor([Dependency(Name = "dataProcessor")]IDataProcessor dataProcessor)
{
_dataProcessor = dataProcessor;
}
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return input;
}
#endregion
}
public class PromptDataProcessor : IDataProcessor
{
#region IDataProcessor Members
public string ProcessData(string input)
{
return "your input is:" + input;
}
#endregion
}
}
- SingletonWithConfiguration
<build-rule type="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest" mode="Singleton" />
- TypeMappingWithConfiguration
<build-rule type="OB_CSMethodInjectionTest.IDataProcessor,OB_CSMethodInjectionTest" mode="Instance" >
<mapped-type type="OB_CSMethodInjectionTest.PromptDataProcessor,OB_CSMethodInjectionTest" />
</build-rule>
- CustomizeStrategys
<object-builder-config xmlns="pag-object-builder" >
<strategies include-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" />
.............
</strategies>
</object-builder-config>
include-default属性决定是否包含Builder对象所内建的Strategys。
九、后记ObjectBuilder是一个相当不错的DependencyInjection实现对象,虽然相对于Spring、Avalon,ObjectBuilder并不是相当的完整,例如没有完整的配置文件驱动特色,但它所具备的高度延展性,可以让我们轻易的达到这个需求,且日后相信ObjectBuilder也会内建这些功能的。

添加至收藏夹