定义具有BuildPart自动发现机制的动态Builder:
C#
public interface IBuilder<T> where T : class, new()
{
T BuildUp();
}
public class Builder<T> : IBuilder<T> where T : class, new()
{
public virtual T BuildUp()
{
IList<BuildStepAttribute> attributes = DiscoveryBuildSteps();
if (attributes == null) return new T(); // 没有BuildPart步骤,退化为Factory模式
T target = new T();
foreach (BuildStepAttribute attribute in attributes)
for (int i = 0; i < attribute.Times; i++)
attribute.Handler.Invoke(target, null);
return target;
}
/// 借助反射获得类型T 所需执行BuildPart()的自动发现机制
protected virtual IList<BuildStepAttribute> DiscoveryBuildSteps()
{
IList<MethodInfo> methods =
AttributeHelper.GetMethodsWithCustomAttribute<BuildStepAttribute>(typeof(T));
if ((methods == null) || (methods.Count == 0)) return null;
BuildStepAttribute[] attributes = new BuildStepAttribute[methods.Count];
for (int i = 0; i < methods.Count; i++)
{
BuildStepAttribute attribute =
AttributeHelper.GetMethodCustomAttribute<BuildStepAttribute>(methods[i]);
attribute.Handler = methods[i];
attributes[i] = attribute;
}
Array.Sort<BuildStepAttribute>(attributes);
return new List<BuildStepAttribute>(attributes);
}
}
Unit Test
[TestClass]
public class TestBuilder
{
public class Car
{
public IList<string> Log = new List<string>();
[BuildStep(2)]
public void AddWheel() { Log.Add("wheel"); }
public void AddEngine() { Log.Add("engine"); }
[BuildStep(1, 2)]
public void AddBody() { Log.Add("body"); }
}
[TestMethod]
public void Test()
{
Builder<Car> builder = new Builder<Car>();
Car car = builder.BuildUp();
Assert.IsNotNull(car);
Assert.AreEqual<int>(2 + 1, car.Log.Count); // 实际只执行了两个方法, 但3次调用
Assert.AreEqual<string>("body", car.Log[0]); // 按照标注的次序执行
Assert.AreEqual<string>("wheel", car.Log[2]); // 按照标注的次序执行
}
}