ObjectBuilder
一.Builder : BuilderBase<BuilderStage>中四个比较重要的概念:
解释:
- BuidlerContext是一个概念型的环境对象,在这个对象中,包含着一组Strategys对象,一组Polices对象,一个Locator对象,
- ObjectBuidler采用Strategys Pipeline(策略流)概念,设计师必须透过Strategy串行来建立对象
- Strategy会透过Polices来寻找『类型/id』对应的Policy对象,使用 它来协助建立指定的对象
- Locator 内部是一个存放对象的对象的字典(WeakRefDictionary<object, object>),便于对象的查找。
- LifeTimeContainer:对象的存放,包含在Locater。(在CreationStrategy中将对象加入的)
强调:
Strategy在架构上是与类型无关的,每个BuidlerContext会拥有一组Strategys对象,我们透过这个Strategys对象来建立任何类型的对象,不管建立的对象类型为何,都会通过这个Strategys Pipeline
对象创建:
Builder.BuildUp(IReadWriteLocator locator, Type typeToBuild, string idToBuild, object existing, params PolicyList[] transientPolicies)
对象创建过程:
首先在 Builder 构造函数中已经提前加入了一些strategy;并加入了了一个DefaultCreationPolicy 的IcreationPolicy类型的policy,BuildUp():
{
…………………….
IBuilderStrategyChain chain = strategies.MakeStrategyChain();
…………………….
IBuilderContext context = MakeContext(chain, locator, transientPolicies);
…………………….
return (Type)chain.Head.BuildUp(context, typeToBuild, existing, idToBuild);
}
Builder会先建立策略链(IBuilderStrategyChain),再构建(IbuilderContext),可以供其他Strategy使用。然后调用IBuilderStrategyChain中第一个Strategy的BuildUp.
BuildUp什么时候结束
几个可以结束的Stratagy: SingletonStrategy, PropertyReflectionStrategy
也就是如果在这几个策略中没有返回Builder.BuildUp中的对象,就会找BuilderStrategyChain下一个Stategy进行BuilderUp(),直到对象返回或者到策略链的结尾;
Example(使用Builder建立Singleton系统):
class Program
{
static void Main(string[] args)
{
Builder builder = new Builder();
Locator locator = new Locator(null);
locator.Add(typeof(ILifetimeContainer), new LifetimeContainer());
builder.Policies.Set<ISingletonPolicy>(new SingletonPolicy(true), typeof(MyClass), null);
MyClass obj1 = builder.BuildUp<MyClass>(locator, null, null);
MyClass obj2 = builder.BuildUp<MyClass>(locator, null, null);
builder.BuildUp<MyClass>(locator, null, null);
Console.WriteLine(obj1 == obj2);
Console.Read();
}
}
class MyClass
{
public void Hello(string aaa)
{
Console.WriteLine("Hello,World!");
}
}
上面的
例子obj1对创建经历了IbuilderStrategyChain的所有strategy才返回,而obj2在SingleTonStrategy中就返回了。
二.依赖注入(Dependency Injection)
好处或意图:
- 是用来降低主程序与对象间的关联
- 同时也能降低对象间的互联性
- 可以简化对象的建立动作,进而让对象更容易使用
常用方式:
- Interface Injection(接口注射)
- Constructor Injection(构造函数注射)
- Setter Injection(设值注射)
例子:
public interface IDataProcessor
{
string ProcessData(string input);
}
public class DummyDataProcessor : IDataProcessor
{
public string ProcessData(string input)
{
return input;
}
}
public class PromptDataProcessor : IDataProcessor
{
public string ProcessData(string input)
{
return "your input is: " + input;
}
}
Interface Injection(接口注射)
public class InputAccept
{
private IDataProcessor _dataProcessor;
public void Inject(IDataProcessor dataProcessor)
{
_dataProcessor = dataProcessor;
}
public void Execute()
{
Console.Write("Please Input some words:");
string input = Console.ReadLine();
input = _dataProcessor.ProcessData(input);
Console.WriteLine(input);
}
}
Constructor Injection(构造函数注入)
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(IDataProcessor dataProcessor)
{
_dataProcessor = dataProcessor;
}
}
Setter Injection(属性来注入)
public class InputAccept
{
private IDataProcessor _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);
}
}
上面的例子只是各种依赖注入的表现形式,IdataProcessor类型的对象_dataProcessor并不会凭空生成,在使用之前必须先给他赋值。
在使用ObjectBuilder时必须先把这些需要值(参数).示例(不完全代码):
ConstructorPolicy creationPolicy = new ConstructorPolicy();
creationPolicy.AddParameter(new ValueParameter(typeof(IDataProcessor), new PromptDataProcessor()));
context.Policies.Set<ICreationPolicy>(creationPolicy, typeof(InputAccept), null);
InputAccept accept = (InputAccept)context.HeadOfChain.BuildUp(context, typeof(InputAccept), null, null);
在ObjectBuilder中每种依赖注入的实现都有相应的Strategy以及相应的属性(Attribute)支持