[]Object Builder Application Block文/黄忠成 ;2006/9/21ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
原文链接:http://blog.csdn.net/code6421/archive/2006/09/25/1282161.aspxƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
整理:吕震宇ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
五、Misc5-1、SingletonStrategySingletonStrategy可于对象实体首次建立后,将实体保留在Context中的Locator内的ILifetimeContainer对象中,之后相同型态、id相同的对象建立动作,都是传回这个对象,这是Singleton模式的实现,如程序27。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序27ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_SingletonTest ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilderContext context = new MyBuilderContext(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new SingletonStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new CreationStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(TestObject), null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj1 = (TestObject)context.HeadOfChain.BuildUp(context, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                typeof(TestObject), null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj2 = (TestObject)context.HeadOfChain.BuildUp(context, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                typeof(TestObject), null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (obj1 == obj2) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Console.WriteLine("Singleton"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    internal class MyBuilderContext : BuilderContext ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public IReadWriteLocator InnerLocator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public BuilderStrategyChain InnerChain = new BuilderStrategyChain(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public PolicyList InnerPolicies = new PolicyList(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public LifetimeContainer lifetimeContainer = new LifetimeContainer(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(new Locator()) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext(IReadWriteLocator locator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            InnerLocator = locator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetLocator(InnerLocator); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            StrategyChain = InnerChain; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetPolicies(InnerPolicies); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (!Locator.Contains(typeof(ILifetimeContainer))) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Locator.Add(typeof(ILifetimeContainer), lifetimeContainer); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
要将一个『类型/id』标示为Singleton,设计者必须于Strategy串行中加入SingletonStrategy对象,并建立一个SingletonPolicy对象,这是一个实现了ISingletonPolicy接口的类别,其构造函数如下。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public SingletonPolicy(bool isSingleton);ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
CreatationStrategy在建立对象后,会从context.Policies中取出『类型/id』对应的ISingletonPolicy对象,以其IsSingleton属性来决定建立的对象是否为Singleton模式,是的话就将该对象实体填入ILifetimeContainer中,同时以DependencyResolutionLocatorKey包装该对象实体,放入Locator中,如下所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
private void RegisterObject(IBuilderContext context, Type typeToBuild, object existing, string idToBuild) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    if (context.Locator != null) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        ILifetimeContainer lifetime = context.Locator.Get<ILifetimeContainer>( ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            typeof(ILifetimeContainer), SearchMode.Local); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        if (lifetime != ;null) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            ISingletonPolicy singletonPolicy = context.Policies.Get<ISingletonPolicy>( ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                typeToBuild, idToBuild); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (singletonPolicy != null && singletonPolicy.IsSingleton) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                context.Locator.Add(new DependencyResolutionLocatorKey( ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                    typeToBuild, idToBuild), existing); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                lifetime.Add(existing); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                //................... ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
以上流程是当该对象实体尚未建立时的流程,假如以BuildUp建立的对象已经存在于Locator中,那么SingletonStrategy的BuildUp方法将直接传回Locator中的对象实体。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public override object BuildUp(IBuilderContext context, Type typeToBuild, object existing, string idToBuild) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    DependencyResolutionLocatorKey key = new DependencyResolutionLocatorKey( ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        typeToBuild, idToBuild); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
  ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    if (context.Locator != null && context.Locator.Contains(key, SearchMode.Local)) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        TraceBuildUp(context, typeToBuild, idToBuild, ""); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        return context.Locator.Get(key); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    return base.BuildUp(context, typeToBuild, existing, idToBuild); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
PS:注意,SingletonStrategy在该对象已经存在于Locator中时,是直接回传,并不会调用后面如MethodExecutionStrategy、PropertySetterStrategy等Strategy。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
5-2、TypeMappingStrategy前面的章节早已使用过TypeMappingStrategy这个对象了,它主要负责『类型/id』的对应,例如将IDataProcessor接口类型的建立,替换成PromptDataProcessor类型,如程序28所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序28ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_TypeMappingTest ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilderContext context = new MyBuilderContext(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new TypeMappingStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new CreationStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            ITypeMappingPolicy policy = new TypeMappingPolicy(typeof(TestObject), null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<ITypeMappingPolicy>(policy, typeof(ITestInterface), null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            ITestInterface obj1 = (ITestInterface)context.HeadOfChain.BuildUp( ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                context, typeof(ITestInterface), null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            obj1.SayHello(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    internal class MyBuilderContext : BuilderContext ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public IReadWriteLocator InnerLocator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public BuilderStrategyChain InnerChain = new BuilderStrategyChain(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public PolicyList InnerPolicies = new PolicyList(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public LifetimeContainer lifetimeContainer = new LifetimeContainer(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(new Locator()) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext(IReadWriteLocator locator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            InnerLocator = locator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetLocator(InnerLocator); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            StrategyChain = InnerChain; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetPolicies(InnerPolicies); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (!Locator.Contains(typeof(ILifetimeContainer))) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Locator.Add(typeof(ILifetimeContainer), lifetimeContainer); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public interface ITestInterface ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        void SayHello(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject : ITestInterface ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public void SayHello() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.WriteLine("TEST"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
TypeMappingStrategy必须搭配TypeMappingPolicy对象使用,TypeMappingPolicy是一个实现ITypeMappingPolicy接口的对象,构造函数声明如下。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public TypeMappingPolicy(Type type, string id)ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
第一个参数是映像的实体类型,以本例来说就是TestObject,第二个参数是识别id,接着将其加入context.Policies中,如下所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
context.Policies.Set<ITypeMappingPolicy>(policy, typeof(ITestInterface), null)ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
当TypeMappingStrategy的BuildUp方法被调用时,它会以『类型/id』取得对应的ITypeMappingPolicy对象,透过它来取得对应的类型,之后将使用这个类型调用下一个Strategy的BuildUp方法,这就是Type Mapping的流程。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
PS:注意,Type Mapping类型必须兼容,如接口->实现、基础类别->衍生类别。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
5-3、BuildAwareStrategyBuildAwareStrategy可以于实现IBuilderAware接口对象建立或释放时,调用对应的OnBuildUp或OnTearDown方法,如程序29所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序29ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_BuildAwareTest ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilderContext context = new MyBuilderContext(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new CreationStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new BuilderAwareStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj = (TestObject)context.HeadOfChain.BuildUp(context, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                typeof(TestObject), null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.HeadOfChain.TearDown(context, obj); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    internal class MyBuilderContext : BuilderContext ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public IReadWriteLocator InnerLocator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public BuilderStrategyChain InnerChain = new BuilderStrategyChain(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public PolicyList InnerPolicies = new PolicyList(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public LifetimeContainer lifetimeContainer = new LifetimeContainer(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(new Locator()) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext(IReadWriteLocator locator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            InnerLocator = locator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetLocator(InnerLocator); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            StrategyChain = InnerChain; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetPolicies(InnerPolicies); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (!Locator.Contains(typeof(ILifetimeContainer))) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Locator.Add(typeof(ILifetimeContainer), lifetimeContainer); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject : IBuilderAware ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        #region IBuilderAware Members ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public void OnBuiltUp(string id) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.WriteLine("Object is build up"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public void OnTearingDown() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.WriteLine("Object is TearDown"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        #endregion ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
与其它的Strategy对象不同,BuilderAwareStrategy并不需要Policy对象的协助,它只是判断建立的对象是否实现了IBuilderAware接口。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
5-4、BuildUp的第三、四个参数截至目前为止,我们的例子在调用BuildUp方法时,第三及四个参数都传入null,这两个参数的用途究竟为何呢?这要先从BuildUp方法的宣告谈起。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
object BuildUp(IBuilderContext context, Type typeToBuild, object existing, string idToBuild);ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
当我们于调用BuildUp方法指定existing为一对象实体时,CreationStrategy将不会建立任何新的对象,只会进行Singleton模式对象的相关动作,然后就调用下一个Strategy对象的BuildUp方法,简单的说!在CreationStrategy后的Strategy仍然会运行,例如Method Injection、Setter Injection都会再次运行,程序30可以协助读者理解这两个参数的用途。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序30ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_ExistingTest ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilderContext context = new MyBuilderContext(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new CreationStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            ConstructorPolicy policy = new ConstructorPolicy(new ValueParameter(typeof(string), "id")); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<ICreationPolicy>(policy, typeof(TestObject), null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj = (TestObject)context.HeadOfChain.BuildUp(context, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                typeof(TestObject), null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj2 = (TestObject)context.HeadOfChain.BuildUp(context, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                typeof(TestObject), obj, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (obj == obj2) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Console.WriteLine("is same object."); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    internal class MyBuilderContext : BuilderContext ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public IReadWriteLocator InnerLocator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public BuilderStrategyChain InnerChain = new BuilderStrategyChain(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public PolicyList InnerPolicies = new PolicyList(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public LifetimeContainer lifetimeContainer = new LifetimeContainer(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(new Locator()) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext(IReadWriteLocator locator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            InnerLocator = locator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetLocator(InnerLocator); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            StrategyChain = InnerChain; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetPolicies(InnerPolicies); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (!Locator.Contains(typeof(ILifetimeContainer))) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Locator.Add(typeof(ILifetimeContainer), lifetimeContainer); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        private string _id; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public string ID ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            get ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                return _id; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public TestObject(string id) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            _id = id; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
BuildUp的第四个参数则主导着ObjectBuilder的类型识别及对象识别机制,请先看程序31的例子。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序31ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_IDTesting ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilderContext context = new MyBuilderContext(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new CreationStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new PropertySetterStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            PropertySetterInfo pi1 = new PropertySetterInfo("ID", new ValueParameter<string>("ID1")); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            PropertySetterPolicy pp1 = new PropertySetterPolicy(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            pp1.Properties.Add("ID", pi1); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<IPropertySetterPolicy>(pp1, typeof(TestObject), "TO1"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            PropertySetterInfo pi2 = new PropertySetterInfo("ID", new ValueParameter<string>("ID2")); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            PropertySetterPolicy pp2 = new PropertySetterPolicy(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            pp2.Properties.Add("ID", pi2); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<IPropertySetterPolicy>(pp2, typeof(TestObject), "TO2"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj1 = (TestObject)context.HeadOfChain.BuildUp(context, typeof(TestObject),null, "TO1"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj2 = (TestObject)context.HeadOfChain.BuildUp(context, typeof(TestObject),null, "TO2"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.WriteLine(obj1.ID); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.WriteLine(obj2.ID); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    internal class MyBuilderContext : BuilderContext ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public IReadWriteLocator InnerLocator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public BuilderStrategyChain InnerChain = new BuilderStrategyChain(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public PolicyList InnerPolicies = new PolicyList(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public LifetimeContainer lifetimeContainer = new LifetimeContainer(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(new Locator()) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext(IReadWriteLocator locator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            InnerLocator = locator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetLocator(InnerLocator); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            StrategyChain = InnerChain; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetPolicies(InnerPolicies); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (!Locator.Contains(typeof(ILifetimeContainer))) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Locator.Add(typeof(ILifetimeContainer), lifetimeContainer); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public string _id; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public string ID ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            get ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                return _id; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            set ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                _id = value; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
在这个例子中,我们建立了两个PropertySetterPolicy对象,分别以ID2、ID2为id加到了context.Policies中,当CreationStrategy建立对象时,它是以下面的程序代码来取得对应的Policy对象。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
private object BuildUpNewObject(IBuilderContext context, Type typeToBuild, object existing, string idToBuild) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    ICreationPolicy policy = context.Policies.Get<ICreationPolicy>(typeToBuild, idToBuild); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    .................. ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
这段程序代码告诉我们一个重点,ObjectBuidler是以『类型/id』来做类型识别动作,也就是说TestObject+”ID1”、TestObject+”ID2”被ObjectBuilder视为两个不同的对象建立动作,你可以分别为其设定专属的Policy对象,也可以于调用BuildUp方法时,指定不同的id来建立同类型,但不同id的对象。另一个会使用『类型/id』来做识别的是DependencyResolutionLocatorKey对象,我们之前常使用它来完成Injection动作,而SingletonStrategy、DependencyParameter也都是运用它来完成所需完成的工作,其构造函数如下所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public DependencyResolutionLocatorKey(Type type, string id)ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
这意味着,当我们使用SingletonStrategy时,可以利用『类型/id』来建立两个同类型但不同id的Singleton对象,如程序32所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序32ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_SingletonTwoTest ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilderContext context = new MyBuilderContext(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new SingletonStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.InnerChain.Add(new CreationStrategy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(TestObject), "ID1"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(TestObject), "ID2"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            context.Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj1 = (TestObject)context.HeadOfChain.BuildUp(context, typeof(TestObject), null, "ID1"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            TestObject obj2 = (TestObject)context.HeadOfChain.BuildUp(context, typeof(TestObject), null, "ID2"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (obj1 == obj2) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Console.WriteLine("Singleton"); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    internal class MyBuilderContext : BuilderContext ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public IReadWriteLocator InnerLocator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public BuilderStrategyChain InnerChain = new BuilderStrategyChain(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public PolicyList InnerPolicies = new PolicyList(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public LifetimeContainer lifetimeContainer = new LifetimeContainer(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(new Locator()) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilderContext(IReadWriteLocator locator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            InnerLocator = locator; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetLocator(InnerLocator); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            StrategyChain = InnerChain; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            SetPolicies(InnerPolicies); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (!Locator.Contains(typeof(ILifetimeContainer))) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                Locator.Add(typeof(ILifetimeContainer), lifetimeContainer); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
这个例子将TestObject+”ID1”、TestObject+”ID2”设定为两个不同的Singleton对象,所以当首次建立并指定id时,所建立出来的两个对象是相异的,也就是说,可以利用『类型/id』来建出两个Singleton系统。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
5-5、StrategyList在本文一开始的范例中,我们使用Builder对象来建立对象,它使用了一个StrategyList对象来处理Strategy串行,这个对象提供了两个重要的方法,一是MakeStrategyChain,它会将StrategyList中的Strategy输出成BuilderStrategyChain对象,这是一个实现了IBuilderStrategyChain接口的对象,也是IBuilderContext所要求的Strategy串行对象。第二个方法是MakeReverseStrategyChain,它会将内含的Strategys反相排序后输出成BuilderStrategyChain对象,这个动作是为了准备TearDown时所需的Strategy串行,还记得前面提过,TearDown的Strategy顺序应该与建立时完全相反,这样才能让对象与其相关的子对象适当的释放。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
5-6、TStageEnumStrategyList是一个泛型对象,它接受一个Enum类型,会依照Enum中所定义的元素来建立Strategy串行或是反相排序,要了解这个设计的原意,我们得先看看ObjectBuilder中所预定义,用来指定给StrategyList的列举。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public enum BuilderStage ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    PreCreation, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Creation, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Initialization, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    PostInitialization ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
读者可以查觉,这与我们先前将Strategy分成四种类型的方式相呼应,StrategyList会依据PreCreation、Creation、Initialization、PostInitialization的顺序来产生BuilderStrategyChain对象,这样就不会因为错置Strategy的顺序,导致程序不正常(例如,先加入CreationStrategy再加入TypeMappingStrategy时,TypeMappingStrategy将无法运作)。Builder对象充份展示了BuilderStage与StrategyList的运用方式。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public Builder(IBuilderConfigurator<BuilderStage> configurator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<TypeMappingStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<SingletonStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<ConstructorReflectionStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<PropertyReflectionStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<MethodReflectionStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<CreationStrategy>(BuilderStage.Creation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<PropertySetterStrategy>(BuilderStage.Initialization); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<MethodExecutionStrategy>(BuilderStage.Initialization); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Strategies.AddNew<BuilderAwareStrategy>(BuilderStage.PostInitialization); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    if (configurator != nulll) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        configurator.ApplyConfiguration(this); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
只要传入的BuilderStage是正确的,不管TypeMappingStrategy是加在CreationStrategy前面或后面,皆可正常运作。不过同一类型的Strategy,但有顺序需求的情况下,仍然要小心调整顺序,程序32示范了运用BuilderStage所带来的优点。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序32ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Collections.Generic; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using System.Text; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
using Microsoft.Practices.ObjectBuilder; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
namespace OB_StrategyListTest ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    class Program ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        static void Main(string[] args) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            MyBuilder builder = new MyBuilder(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            ITypeMappingPolicy policy = new TypeMappingPolicy(typeof(TestObject), null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            builder.Policies.Set<ITypeMappingPolicy>(policy, typeof(ITestInterface), null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            ITestInterface obj1 = builder.BuildUp<ITestInterface>(new Locator(), null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Console.Read(); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class MyBuilder : BuilderBase<BuilderStage> ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilder() ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            : this(null) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        public MyBuilder(IBuilderConfigurator<BuilderStage> configurator) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<CreationStrategy>(BuilderStage.Creation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<TypeMappingStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<SingletonStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<ConstructorReflectionStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<PropertyReflectionStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<MethodReflectionStrategy>(BuilderStage.PreCreation); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<PropertySetterStrategy>(BuilderStage.Initialization); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<MethodExecutionStrategy>(BuilderStage.Initialization); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Strategies.AddNew<BuilderAwareStrategy>(BuilderStage.PostInitialization); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            Policies.SetDefault<ICreationPolicy>(new DefaultCreationPolicy()); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            if (configurator != null) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
                configurator.ApplyConfiguration(this); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public interface ITestInterface ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public class TestObject : ITestInterface ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
5-6、PolicyList BuilderContext所定义的Policies对象类型为PolicyList,PolicyList对象以Dictionary对象来储存设计者所加入的Policy对象,其中用来作为键值的BuilderPolicyKey类别构造函数如下。 ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public BuilderPolicyKey(Type policyType, Type typePolicyAppliesTo, string idPolicyAppliesTo)ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
第一个参数为policyType,也就是ICrationPolicy、ITypeMappingPolicy等之类,第二个参数是对应的类型,第三个参数则是id。设计者可以调用PolicyList.Set方法来加入一个Policy至内部的存储器中,该方法会依据传入的参数建立BuilderPolicyKey做为键值,然后将Policy加到Dictionary中,如下所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public void Set(Type policyInterface, IBuilderPolicy policy, Type typePolicyAppliesTo, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
string idPolicyAppliesTo) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    BuilderPolicyKey key = new BuilderPolicyKey(policyInterface, typePolicyAppliesTo, idPolicyAppliesTo); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    lock (lockObject) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        policies[key] = policy; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
另一个泛型类型的Set方法也可以达到同样的效果。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public void Set<TPolicyInterface>(TPolicyInterface policy, Type typePolicyAppliesTo, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    string idPolicyAppliesTo) where TPolicyInterface : IBuilderPolicy ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    Set(typeof(TPolicyInterface), policy, typePolicyAppliesTo, idPolicyAppliesTo); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
设计者可以透过PolicyList.Get方法来取得对应的Policy对象,该方法如下所示。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public TPolicyInterface Get<TPolicyInterface>(Type typePolicyAppliesTo, string idPolicyAppliesTo) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    where TPolicyInterface : IBuilderPolicy ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    return (TPolicyInterface)Get(typeof(TPolicyInterface), typePolicyAppliesTo, idPolicyAppliesTo); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
} ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public IBuilderPolicy Get(Type policyInterface, Type typePolicyAppliesTo, string idPolicyAppliesTo) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    BuilderPolicyKey key = new BuilderPolicyKey(policyInterface, ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        typePolicyAppliesTo, idPolicyAppliesTo); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    lock (lockObject) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        IBuilderPolicy policy; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        if (policies.TryGetValue(key, out policy)) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            return policy; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        BuilderPolicyKey defaultKey = new BuilderPolicyKey(policyInterface, null, null); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        if (policies.TryGetValue(defaultKey, out policy)) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
            return policy; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
        return null; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    } ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
}
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
SetDefault则可以用一个Policy来提供给所有类型使用,Get方法在找不到对应『类型/id』对应的Policy时,就会以该Policy回传。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
六、LocatorObjectBuilder利用Locator对象来实现Service Locator,也利用Locator来进行Dependency Injection,在ObjectBuilder的架构上,Locator有两种类型,一是Readonly Locator,顾名思义,这类Locator只允许读取、不允许新增。二是ReadWriteLocator,它是允许新增、读取类的Locator。我们可以从Visual Studio 2005的Class Diagram来观察ObjectBuilder中的Locator阶层架构。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
图7ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
6-1、Readonly LocatorObjectBuidler定义了一个IReadableLocator接口,所有的Locator都必须直接或间接实现此接口,内建实现此接口的类别是ReadableLocator,它是一个抽象类。真正完成实现可用的是ReadOnlyLocator,这个Locator只允许读取,不允许新增。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
6-2、ReadWrite LocatorObjectBuilder中支持读与写的Locator是ReadWriterLocator,与ReadOnlyLocator一样,它也是一个抽象类,真正完成实现的是Locator类别。附带一提,虽然Locator定义了蛮清楚的阶层,但是BuilderContext只支持实现IReadWriterLocator接口的Locator。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
6-3、WeakRefDictionary and LocatorLocator类别是我们一直都在使用的Locator,它是一个继承自ReadWriterLocator的类别,值得一提的是,它使用一个WeakRefDictionary来储存设计者所放入Locator的对象,WeakRefDictionary内部对于每个元素都会以WeakReference封装,这意味着,Locator中的元素并无法保证一直都存在,因为CLR会在内存拮据时,先行释放WeakRefernce所封装的对象,这点读者必须谨记。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
七、Extending ObjectBuilderObjectBuilder除了支持三种Dependency Injection模式、Service Locator之外,最大的魅力应该来自于具高度延展性的架构,设计者可以透过撰写Strategy、Policy、Locator等类别来参与对象的建立动作,本章以两个范例来证明这点,一是EventSetterStrategy,它提供Event Injection功能,二是PoolStrategy,提供Pool模式的对象建立。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
7-1、EventSetterStrategyObjectBuidler提供了Constructor Injection、Interface Injection(Method Ijection)、Setter Injection(Property Injection)三种Injection模式,虽然ObjectBuilder只提供了Propety式的Setter Injection,不过我们可以藉助于ObjectBuilder高度的延展性架构,让ObjectBuidler也能支持Event Injection。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
  • IEventSetterInfo
Event Injection与Property Injection同属Setter Injection模式,两者运作的模式也极为相似,ObjectBuilder在Property Injection部份是由ProperySeterInfo、PropertySetterPolicy及PropertySetterStrategy三个类别所构筑而成,我们可以依循这个既定架构,实现Event Injection功能。首要必须定义一个IEventSetterInfo接口,这相对于IPropertySetterInfo接口之于Property Injection。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序33ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public interface IEventSetterInfo ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    object GetValue(IBuilderContext context, Type type, string id, EventInfo propInfo); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    EventInfo SelectEvent(IBuilderContext context, Type type, string id); ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
} ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
IEventSetterInfo接口定义了两个方法,SelectEvent方法是用来取得欲Injection事件的EventInfo对象,EventSetterStrategy会调用此方法来取得欲Injection事件的EventInfo对象,然后透过EventInfo.AddHandler来进行注入动作,这个注入动作所使用的值是透过调用IEventSetterInfo.GetValue方法来取得,此接口的实现程序代码如34。ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
程序34ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
public sealed class EventSetterInfo : IEventSetterInfo ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
{ ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    private string _name = null; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    private IParameter _value = null; ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    #region IEventSetterInfo Members ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    public object GetValue(IBuilderContext context, Type type, string id, EventInfo propInfo) ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC’
    { ƒ['²7 ‘å<www.netcsharp.cn]i[¨HPwêC