类中具有 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);
  }
}

类中具有 2 个泛型类型的方法,具有 1 个泛型类型

我看到您当前的方法存在以下问题:

  • 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;
   }
 }