类中具有 2 个泛型类型的方法,具有 1 个泛型类型
本文关键字:泛型类型 方法 具有 | 更新日期: 2023-09-27 17:56:01
>我有以下内容:
public class P1 {
public P2 P2 { get; set; }
public P4 P4 { get; set; }
}
public class P2 {
public P3 P3 { get; set; }
}
public class P3 { }
public class P4 { }
我需要 P1 的映射器,如下所示:
Mapper mapper = new Mapper<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<P1> mapper = Mapper.For<P1>()
.Add(p1 => p1.P2).And(p2 => p2.P3);
我认为这些方法应该返回映射器,但实际上我想创建一个映射器......
K 只是在调用方法时定义表达式的一种方式。
有谁知道如何做到这一点?
更新
使用延续映射器回答:
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);
}
}
我看到您当前的方法存在以下问题:
- 在
Add
之前应该不可能做And
。 - 在
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>(...);
}
}
显然,您必须将表达式列表的状态传递给新类,这留给读者作为练习。作为额外的奖励,如果需要,您甚至可以使您的类不可变。
实质上,您不希望将方法类型绑定到类类型,因此需要使用 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;
}
}