2009-04-08 46 views

Trả lời

62

Bạn không thể bỏ qua giữa chúng vì chúng không phải là loại tương tự. Tuy nhiên, bạn có hiệu quả có thể thêm một chuyển đổi trong cây biểu hiện:

using System; 
using System.Linq.Expressions; 

class Test 
{ 
    // This is the method you want, I think 
    static Expression<Func<TInput,object>> AddBox<TInput, TOutput> 
     (Expression<Func<TInput, TOutput>> expression) 
    { 
     // Add the boxing operation, but get a weakly typed expression 
     Expression converted = Expression.Convert 
      (expression.Body, typeof(object)); 
     // Use Expression.Lambda to get back to strong typing 
     return Expression.Lambda<Func<TInput,object>> 
      (converted, expression.Parameters); 
    } 

    // Just a simple demo 
    static void Main() 
    { 
     Expression<Func<string, DateTime>> x = text => DateTime.Now; 
     var y = AddBox(x);   
     object dt = y.Compile()("hi"); 
     Console.WriteLine(dt); 
    }   
} 
+0

@JonSkeet Expression.Convert không phải là luôn luôn là một ý tưởng tốt. Xem câu trả lời của tôi. – Rookian

8

Dựa trên mã từ Jon (nhờ btw), bạn có thể mang nó một bước xa hơn cho sự linh hoạt hoàn chỉnh:

public static Expression<Func<TModel, TToProperty>> Cast<TModel, TFromProperty, TToProperty>(Expression<Func<TModel, TFromProperty>> expression) 
{ 
    Expression converted = Expression.Convert(expression.Body, typeof(TToProperty)); 

    return Expression.Lambda<Func<TModel, TToProperty>>(converted, expression.Parameters); 
} 
+0

Có ví dụ sử dụng nào về điều này không? –

23

Những câu trả lời từ RobJon Skeet có một vấn đề.

Bạn nhận được một cái gì đó giống như x => Convert(x.PropertyName), nhưng thường ví dụ cho ASP.NET MVC bạn muốn một biểu hiện như thế này x => x.PropertyName

Vì vậy Expression.Convert"ô nhiễm" biểu thức đối với một số trường hợp.

Giải pháp:

public static class LambdaExpressionExtensions 
{ 
    public static Expression<Func<TInput, object>> ToUntypedPropertyExpression<TInput, TOutput> (this Expression<Func<TInput, TOutput>> expression) 
    { 
     var memberName = ((MemberExpression)expression.Body).Member.Name; 

     var param = Expression.Parameter(typeof(TInput)); 
     var field = Expression.Property(param, memberName); 
     return Expression.Lambda<Func<TInput, object>>(field, param); 
    } 
} 

Cách sử dụng:

Expression<Func<T, DateTime>> expression = ...; 
Expression<Func<T, object>> expr = expression.ToUntypedPropertyExpression(); 
+7

Điều này dường như không hoạt động. Ví dụ, tôi dường như không thể chuyển đổi 'Int32' thành' đối tượng'; đó là những gì các cuộc gọi 'Chuyển đổi 'là cho. Nếu không có nó tôi nhận được một 'ArgumentException'. Đang thử phiên bản 'DateTime', cùng một điều. Nếu điều này làm việc cho bạn, tôi đoán bạn đã làm nó với một loại tham chiếu. –

0

Chỉ cần xác định ra TResult như đối tượng và biên dịch biểu thức, nó hoạt động cho tất cả các loại dữ liệu;

Expression<Func<string, object>> dateExp = text => DateTime.Now; 
object dt = dateExp.Compile()("hi"); 
Console.WriteLine(dt); 

Fiddle sample here

Các vấn đề liên quan