Tôi đã cố gắng xây dựng điều này dựa trên câu trả lời của @Andrey Naumov . Có thể đây là một cải tiến nhỏ.
public sealed class Lambda<S>
{
public static Func<S, T> CreateFunc<T>(Func<S, T> func)
{
return func;
}
public static Expression<Func<S, T>> CreateExpression<T>(Expression<Func<S, T>> expression)
{
return expression;
}
public Func<S, T> Func<T>(Func<S, T> func)
{
return func;
}
public Expression<Func<S, T>> Expression<T>(Expression<Func<S, T>> expression)
{
return expression;
}
}
Trong đó tham số kiểu S
là tham số chính thức (tham số đầu vào, bắt buộc tối thiểu để suy ra phần còn lại của các kiểu). Bây giờ bạn có thể gọi nó như sau:
var l = new Lambda<int>();
var d1 = l.Func(x => x.ToString());
var e1 = l.Expression(x => "Hello!");
var d2 = l.Func(x => x + x);
//or if you have only one lambda, consider a static overload
var e2 = Lambda<int>.CreateExpression(x => "Hello!");
Bạn có thể có thêm quá tải cho Action<S>
và Expression<Action<S>>
tương tự trong cùng một lớp. Đối với khác được xây dựng trong đại biểu và biểu hiện các loại, bạn sẽ phải viết các lớp riêng biệt như Lambda
, Lambda<S, T>
, Lambda<S, T, U>
, vv
Lợi thế của điều này mà tôi thấy so với cách tiếp cận ban đầu:
Một đặc tả kiểu nhỏ hơn (chỉ tham số chính thức cần được chỉ định).
Điều này cho phép bạn tự do sử dụng nó để chống lại bất kỳ Func<int, T>
, không chỉ khi T
được nói string
, như được hiển thị trong các ví dụ.
Hỗ trợ các biểu thức ngay lập tức. Trong cách tiếp cận trước đó, bạn sẽ phải chỉ định lại các loại, như:
var e = Lambda<Expression<Func<int, string>>>.Cast(x => "Hello!");
//or in case 'Cast' is an instance member on non-generic 'Lambda' class:
var e = lambda.Cast<Expression<Func<int, string>>>(x => "Hello!");
cho các biểu thức.
Việc mở rộng lớp cho các kiểu đại biểu (và biểu thức) khác cũng tương tự như trên.
var e = Lambda<Action<int>>.Cast(x => x.ToString());
//or for Expression<Action<T>> if 'Cast' is an instance member on non-generic 'Lambda' class:
var e = lambda.Cast<Expression<Action<int>>>(x => x.ToString());
Theo cách tiếp cận của tôi, bạn chỉ phải khai báo các kiểu một lần (ít hơn một lần đối với Func
s).
Một cách khác để triển khai câu trả lời của Andrey giống như không hoàn toàn chung chung
public sealed class Lambda<T>
{
public static Func<Func<T, object>, Func<T, object>> Func = x => x;
public static Func<Expression<Func<T, object>>, Expression<Func<T, object>>> Expression = x => x;
}
Vì vậy, mọi thứ giảm xuống:
var l = Lambda<int>.Expression;
var e1 = l(x => x.ToString());
var e2 = l(x => "Hello!");
var e3 = l(x => x + x);
Điều đó thậm chí còn ít hơn khi gõ, nhưng bạn sẽ mất đi sự an toàn khi gõ và imo, điều này không đáng.