[英]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.