簡體   English   中英

具有 1 個泛型類型的類中具有 2 個泛型類型的方法

[英]Methods with 2 generic types in class with 1 generic type

我有以下幾點:

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 代碼只允許這樣做:

  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);

我認為這些方法應該返回 Mapper 但實際上我想創建一個 Mapper ...

K 只是在調用方法時定義表達式的一種方式。

有誰知道如何做到這一點?

更新

用 ContinuationMapper 回答:

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並將 and 綁定到最后一個屬性,則需要提供一個包裝類,例如

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM