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

时间:2016-07-08 19:31:18

标签: c#

我有以下内容:

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

2 个答案:

答案 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;
   }
 }