我有以下内容:
Mapper mapper = new Mapper<P1>();
我需要一个Mapper for P1,如下所示:
Mapper<P1> mapper = Mapper.For<P1>()
.Add(p1 => p1.P2).And(p2 => p2.P3)
.Add(p1 => p1.P4);
但我想按如下方式使用它:
public class Mapper {
public static Mapper<T> For<T>() {
return new Mapper<T>();
}
}
public class Mapper<T> {
private List<LambdaExpression> _expressions = new List<LambdaExpression>();
public Mapper<T> Add<K>(Expression<Func<T, K>> expression) {
// Add expression to expressions
return this;
}
public Mapper<T> And<K>(Expression<Func<T, K>> expression) {
// Add expression to expressions
return this;
}
}
所以我有:
Mapper<P1> mapper = Mapper.For<P1>()
.Add(p1 => p1.P2).And(p1 => p1.P2.P3);
我的问题是如何处理子属性。
请注意,我的Mapper代码只允许执行此操作:
Mapper<P1> mapper = Mapper.For<P1>()
.Add(p1 => p1.P2).And(p2 => p2.P3);
而不是这个:
public class Mapper<T> {
protected List<LambdaExpression> Paths { get; set; } = new List<LambdaExpression>();
public ContinuationMapper<T, TCont> Add<TCont>(Expression<Func<T, TCont>> path) {
Paths.Add(path);
return new ContinuationMapper<T, TCont>(Paths);
}
}
public class ContinuationMapper<TBase, TCurrent> : Mapper<TBase> {
public ContinuationMapper(List<LambdaExpression> paths) {
Paths = paths;
}
public ContinuationMapper<TBase, TNext> And<TNext>(Expression<Func<TCurrent, TNext>> path) {
base.Paths.Add(path);
return new ContinuationMapper<TBase, TNext>(base.Paths);
}
}
我认为这些方法应该返回Mapper,但实际上我想创建一个Mapper ......
K只是在调用方法时定义表达式的一种方法。
有谁知道怎么做?
更新
使用ContinuationMapper回答:
{{1}}
答案 0 :(得分:1)
我看到您当前的方法存在以下问题:
And
之前执行Add
。And
(或Add
)结束时,您有两种类型的信息类型:基本类型新Add
的新And
和延续类型。您不能在编译时将这种类型的信息“存储”在只有一个通用参数的泛型类型中。幸运的是,类型系统可以在这里提供帮助,如果我们将你的一个班级分成两部分:
public class Mapper<T>
{
public ContinuationMapper<T, TCont> Add<TCont>(Expression<Func<T, TCont>> expression) {
// ...
return new ContinuationMapper<T, TCont>(...);
}
}
public class ContinuationMapper<TBase, TCurrent> : Mapper<TBase>
{
public ContinuationMapper<TBase, TNext> And<TNext>(Expression<Func<TCurrent, TNext>> expression) {
// ...
return new ContinuationMapper<TBase, TNext>(...);
}
}
显然,您必须将表达式列表的状态传递给新类,这将留给读者练习。作为额外的奖励,如果你愿意,你甚至可以让你的课程不变。
答案 1 :(得分:0)
实质上,您不希望将方法类型绑定到类类型,因此您需要使用2个新的泛型类型。有点像以下。
public Mapper<T> Add<V,K>(Expression<Func<V, K>> expression) {
// Add expression to expressions
return this;
}
public Mapper<T> And<V,K>(Expression<Func<V, K>> expression) {
// Add expression to expressions
return this;
}
示例:
Mapper<P1> mapper = Mapper.For<P1>()
.Add((P1 p1) => p1.P2).And((P2 p2) => p2.P3)
.Add((P1 p1) => p1.P4);
如果您希望将Add
绑定到T
并将其绑定到最后一个属性,则需要提供一个包装类,如
Mapper<T,V>{
public Mapper<T> Add<V>(Expression<Func<T, V>> expression) {
// Add expression to expressions
return Mapper.Wrap<T,V>(this);
}
public Mapper<T> And<V>(Expression<Func<V, K>> expression) {
// Add expression to expressions
return this;
}
}