2009-03-24 43 views
7

tôi có phương pháp khuyến nông:Thay đổi tham số từ chức năng lambda để biểu thức lambda

public static IQueryable<TResult> WithFieldLike<TResult>(
    this IQueryable<TResult> query, 
    Func<TResult, string> field, 
    string value) 
{ 
    Expression<Func<TResult, bool>> expr = 
     trans => field(trans).Contains(value); 
    return query.Where(expr); 
} 

Tôi cần lĩnh vực tham số thay đổi để gõ: Expression>. Sẽ là một cái gì đó như thế nào.

public static IQueryable<TResult> WithFieldLike<TResult>(
    this IQueryable<TResult> query, 
    Expression<Func<TResult, string>> field, 
    string value) 
{ 
    Expression<Func<TResult, bool>> expr = ??? 
    return query.Where(expr); 
} 

Cuộc gọi của phương pháp này là:

var query7 = query.WithFieldLike(trans => trans.DeviceModelNumber, "ber_3"); 

Làm thế nào tôi nên xây dựng các "expr" trong trường hợp này? Hãy giúp tôi.

+0

Vui lòng thêm ngôn ngữ để các thẻ. – Svante

Trả lời

6

deconstruct field và tạo ra một biểu hiện mới, một cái gì đó như thế này:

var expr = Expression.Lambda<Func<TResult, bool>> (
    Expression.Call (field.Body, typeof (string).GetMethod ("Contains"), 
     Expression.Constant (value)), field.Parameters) ; 

(sửa theo tinh maxs trong comments)

+0

Vấn đề là tôi không thể xây dựng biểu thức "Chứa". Cách xây dựng biểu thức "Bằng" tôi biết. – Maxs

+0

Rất tiếc, xin lỗi - câu trả lời đã chỉnh sửa –

+0

Cảm ơn bạn. Điều này hoạt động hoàn hảo. – Maxs

1

Sử dụng Compile để có được lambda trở ra:

Expression<Func<TResult, bool>> expr = 
    trans => field.Compile()(trans).Contains(value); 

Chỉnh sửa: Lỗi chính - trình biên dịch không khí của tôi thất bại tôi. Sau khi biên dịch, bạn sẽ có được đại biểu. Tuy nhiên, bạn vẫn cần phải gọi nó để nhận được chuỗi để gọi Chứa.

+0

Sẽ là lỗi biên dịch: 'System.Func ' không chứa định nghĩa cho 'Chứa' và không có phương pháp mở rộng 'Chứa' chấp nhận đối số đầu tiên của loại 'System.Func ' có thể được tìm thấy (bạn đang thiếu một chỉ thị bằng cách sử dụng hoặc một tham chiếu lắp ráp?) – Maxs

+0

@Maxs: Vâng - Tôi loại hơi say lên toàn bộ "chuyển đổi nó sang một biểu thức" một phần. Điểm đứng mặc dù - sử dụng biên dịch để có được lambda, và sử dụng nó như bình thường. –

4

Bạn sẽ cần phải sử dụng Expression.Invoke; một cái gì đó tương tự (chưa được kiểm tra):

public static IQueryable<TResult> WithFieldLike<TResult>(
    this IQueryable<TResult> query, 
    Expression<Func<TResult, string>> field, 
    string value) 
{ 
    var param = Expression.Parameter(typeof(TResult), "x"); 
    var expr = Expression.Lambda<Func<TResult, bool>>(
     Expression.Call(Expression.Invoke(field, param), 
      "Contains", null, Expression.Constant(value)), param); 

    return query.Where(expr); 
} 

(chỉnh sửa: cố định)

+1

Cảm ơn. Điều này cũng hoạt động. Nhưng tạo biểu thức không tương thích với lệnh gọi dịch vụ dữ liệu ADO.NET. – Maxs

+1

Gotta yêu Luật trừu tượng bị rò rỉ ... nó hoạt động với một số nhưng không phải tất cả ;-p –