第一個要準備的就是解決一個對象是如何構造的. 我們選擇很多:
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>