第一个要准备的就是解决一个对象是如何构造的. 我们选择很多:
1. 使用ObjectBuilder库;
2. 强迫所有需要创建的对象都支持 where T : new();
3. 做一个轻量级的对象构造 "泵";
第一中选择很企业级, 但是可以用于业务逻辑, 对于工程化的设计模式库而言, 似乎有点本末倒置了, 有些重, 不过可以算作一种选择; 第二种选择, "Cut"对于客户需用要求太苛刻了, 逼着别人 "削足适履"; 第三种选择, 做个轻便的, Portable的ObjectBuilder, 可以去掉那些BuilderStrategy, Builder Policy.
客户层需要对面对两个new()替代方式, 其思路有点坏了"依赖于抽象, 而不依赖于现实"的规矩, 那么可以抽象一层, 为了使用上的习惯一样, 叫IBuilderObject好了.
但最终选谁来实现IObjectBuilder? 为了不和ObjectBuilder的信徒冲突, 为了不和支持被 "Cut" 掉的那个方案的同事发生冲突, 写在配置文件中,
其代码如下:
using System;
namespace Company.Product.Common
{
/// <summary>
/// 根据类型名称生成类型实例
/// </summary>
public interface IObjectBuilder
{
/// <summary>
/// 创建类型实例
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="args">构造函数参数</param>
/// <returns>指定类型T的新实例</returns>
T BuildUp<T>(object[] args);
/// <summary>
/// 创建类型实例
/// <remarks>该方法仅适用于有无参构造函数的类型</remarks>
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <returns>指定类型T的新实例</returns>
T BuildUp<T>() where T : new();
/// <summary>
/// 按照目标返回的类型, 加工指定类型名称对应的类型实例
/// 目标类型可以为接口, 抽象类等抽象类型, typeName一般为实体类名称
/// </summary>
/// <typeparam name="T">目标返回类型</typeparam>
/// <param name="typeName">类型名称</param>
/// <returns>按照目标返回类型加工好的一个实例</returns>
T BuildUp<T>(string typeName);
/// <summary>
/// 按照目标类型, 通过调用指定名称类型的构造函数, 生成目标类型实例
/// </summary>
/// <typeparam name="T">目标返回类型</typeparam>
/// <param name="typeName">类型名称</param>
/// <param name="args">构造函数参数</param>
/// <returns>按照目标返回类型加工好的一个实例</returns>
T BuildUp<T>(string typeName, object[] args);
}
}
using System;
namespace Company.Product.Common
{
public class TypeCreator : IObjectBuilder
{
#region IObjectBuilder 成员
public T BuildUp<T>(object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}
public T BuildUp<T>() where T : new()
{
return Activator.CreateInstance<T>();
}
public T BuildUp<T>(string typeName)
{
return (T)Activator.CreateInstance(Type.GetType(typeName));
}
public T BuildUp<T>(string typeName, object[] args)
{
return (T)Activator.CreateInstance(Type.GetType(typeName), args);
}
#endregion
}
}
配置文件:
<configuration>
<configSections>
<sectionGroup name="marvellousWorks.practicalPattern.common" type="fake">
<section name="objectBuilder" type="fake"/>
</sectionGroup>
</configSections>
<marvellousWorks.practicalPattern.common>
<objectBuilder type="MarvellousWorks.PracticalPattern.Common.TypeCreator, MarvellousWorks.PracticalPattern.Common" />
</marvellousWorks.practicalPattern.common>
</configuration>