我们在整个应用程序的几个地方使用构建器模式。 到目前为止,我们已经在我们的一些构建器中编写了以下方法,这些方法运行良好。
public class MyBuilderClass
{
private MyConcreteType entity;
public MyBuilderClass() { this.entity = new MyConcreteType(); }
public MyBuilderClass With<TProperty>(Expression<Func<T, TProperty>> expressionToFindProperty, TProperty valueToSet)
{
MemberExpression member = (MemberExpression)expressionToFindProperty.Body;
PropertyInfo property = (PropertyInfo)member.Member;
property.SetValue(this.entity, valueToSet, null);
return this;
}
}
允许我们按照以下方式执行以下操作:
new MyBuilderClass().With(x=> x.MyProperty, "TheValue")
并且它推断出MyProperty
在这种情况下是一个字符串。
这很有用,所以我们希望能够以抽象的方式进行。有点像:
public abstract class AbstractBuilder<T, TBuilder> where TBuilder : AbstractBuilder<T, TBuilder>
{
internal T entity;
public TBuilder With<TProperty>(Expression<Func<T, TProperty>> expressionToFindProperty, TProperty valueToSet)
{
// Example usage: With(x => x.TrackingRecord, new TrackingRecord());
MemberExpression member = (MemberExpression)expressionToFindProperty.Body;
PropertyInfo property = (PropertyInfo)member.Member;
property.SetValue(this.entity, valueToSet, null);
return (TBuilder)this;
}
public T Build()
{
return this.entity;
}
}
那么我们的混凝土建造者将遵循:
public class MyBuilderClass : AbstractBuilder<MyType, MyBuilderClass>
{
// Code here
}
在上面的示例中,我们需要使用MyBuilderClass : AbstractBuilder<MyType, MyBuilderClass>
,引用MyBuilderClass
两次,以便我们的抽象构建器的TBuilder
泛型类型正确运行。
在这种情况下,我们可以对AbstractBuilder
进行更改,以便可以缩短子类的语法:
public class MyBuilderClass : AbstractBuilder<PaymentRecord, MyBuilderClass>
到
public class MyBuilderClass : AbstractBuilder<PaymentRecord>
其中TBuilder
被推断为MyBuilderClass
?
我很想获得语法上的糖,而不必明确传递构建器的类型。
答案 0 :(得分:4)
不,仿制药不喜欢做那样的事情。您需要传递类型参数。
总旁注;如果你经常建造这样的物体,反射会变得相当昂贵。
答案 1 :(得分:0)
可能会让catch
函数返回with
例如:
AbstractBuilder<TType>
然后你可以进行所需的简单扩展:
public abstract class AbstractBuilder<T>
{
internal T entity;
public AbstractBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> expressionToFindProperty, TProperty valueToSet)
{
// Example usage: With(x => x.TrackingRecord, new TrackingRecord());
MemberExpression member = (MemberExpression)expressionToFindProperty.Body;
PropertyInfo property = (PropertyInfo)member.Member;
property.SetValue(this.entity, valueToSet, null);
return this;
}
public T Build()
{
return this.entity;
}
}
并称之为:
public class MyBuilderClass : AbstractBuilder<PaymentRecord>
缺点是,在调用var builder = new MyBuilderClass();
var record = builder
.With(f => f.TrackingRecord, new MyTrackingRecord())
.Build();
之后,它会将您的流畅api限制为抽象类,除非您重写函数调用以返回特定的构建器类型。