2011-08-17 41 views
8

Tôi nên xây dựng cây biểu thức cho string.IndexOf("substring", StringComparison.OrdinalIgnoreCase) như thế nào?Cây biểu thức cho phương thức String.IndexOf

Tôi có thể làm cho nó hoạt động mà không có đối số thứ hai: StringComparison.OrdinalIgnoreCase. Đây là những nỗ lực của tôi cho đến nay:

var methodCall = typeof (string).GetMethod("IndexOf", new[] {typeof (string)}); 
Expression[] parms = new Expression[]{right, Expression.Constant("StringComparison.OrdinalIgnoreCase", typeof (Enum))}; 
var exp = Expression.Call(left, methodCall, parms); 
return exp; 

Cũng cố gắng này:

var methodCall = typeof (string).GetMethod(method, new[] {typeof (string)}); 
Expression[] parms = new Expression[]{right, Expression.Parameter(typeof(Enum) , "StringComparison.OrdinalIgnoreCase")}; 
var exp = Expression.Call(left, methodCall, parms); 
return exp; 

Hãy nhớ rằng tôi có thể lấy nó làm việc nếu tôi bỏ qua các tham số OrdinalIgnoreCase.

Cảm ơn

+2

Như mọi khi, khi bạn có vấn đề bạn nên nói những gì đang xảy ra với những gì bạn đã thử - bạn có ngoại lệ, lỗi biên dịch, hành vi sai? Nếu đó là lỗi của một số loại, lỗi là gì? –

+0

Xin lỗi. Tôi sẽ ghi nhớ điều đó trong lần tới khi đặt câu hỏi. Tôi đã nhận được một ArgumentException. – ashokgelal

+0

Cần trợ giúp: [how-do-i-tạo-một-biểu-tree-to-đại diện-chuỗi-chứa-in-in] (http://stackoverflow.com/questions/278684/how-do-i-create- a-expression-tree-to-represent-string-containssterm-in-c) – nawfal

Trả lời

11

Tôi nghi ngờ có hai vấn đề.

Đầu tiên là cách bạn đang nhận được phương pháp này - bạn hỏi cho một phương pháp chỉ có một tham số chuỗi duy nhất, thay vì một với hai tham số:

var methodCall = typeof (string).GetMethod("IndexOf", 
          new[] { typeof (string), typeof(StringComparison) }); 

Thứ hai là giá trị bạn đang đem lại - nó phải là giá trị thực tế của các hằng số, không phải là một chuỗi:

Expression[] parms = new Expression[] { right, 
    Expression.Constant(StringComparison.OrdinalIgnoreCase) }; 

EDIT: đây là một mẫu làm việc hoàn chỉnh:

using System; 
using System.Linq.Expressions; 

class Test 
{ 
    static void Main() 
    { 
     var method = typeof (string).GetMethod("IndexOf", 
       new[] { typeof (string), typeof(StringComparison) }); 

     var left = Expression.Parameter(typeof(string), "left"); 
     var right = Expression.Parameter(typeof(string), "right"); 

     Expression[] parms = new Expression[] { right, 
       Expression.Constant(StringComparison.OrdinalIgnoreCase) }; 

     var call = Expression.Call(left, method, parms); 
     var lambda = Expression.Lambda<Func<string, string, int>> 
      (call, left, right); 

     var compiled = lambda.Compile(); 
     Console.WriteLine(compiled.Invoke("hello THERE", "lo t")); 
    } 
} 
+0

Có cách nào để thực hiện tương tự cho phương thức 'contains' không? – atp9

+0

@ atp9: Có. Bạn đã thử những gì và điều gì đã xảy ra? –

+0

Tôi đã thử một cái gì đó như thế này: 'MethodInfo method = typeof (string).GetMethod ("Chứa", mới [] {typeof (string), typeof (StringComparison)}); var expressionbody = System.Linq.Expressions.Expression.Call (prop, method, new [] {valuetocompare, System.Linq.Expressions.Expression.Constant (StringComparison.OrdinalIgnoreCase)}); 'Nhưng cái này cho tôi một lỗi – atp9

0

tôi đã không kiểm tra phần còn lại của nó, nhưng nếu chỉ enum đặt ra vấn đề:

Expression.Constant(StringComparison.OrdinalIgnoreCase) 

hoặc

Expression.Constant(Enum.Parse(typeof(StringComparison), "OrdinalIgnoreCase"), typeof(Enum)); 

Và bạn có nhiều lựa chọn. Hoặc kiểm tra câu trả lời của tôi here.

Chỉnh sửa: quên dấu ngoặc đơn.

3

Cách đơn giản nhất để làm điều đó là để có được nó thông qua một lambda như thế này:

//the compiler will convert the lambda into an expression 
Expression<Func<string, string, int>> expression = (s1, s2) => s1.IndexOf(s2, StringComparison.OrdinalIgnoreCase); 
//compile the expression so we can call it 
var func = expression.Compile(); 
//outputs 2 
Console.WriteLine(func("Case Sensitive", "se sensitive")); 

Đây là nhiều hơn nữa có thể đọc được và duy trì hơn bằng tay xây dựng một cây biểu thức.

Tôi liên tục bị ngạc nhiên bởi số lượng người lặn thẳng vào xây dựng cây biểu diễn theo cách thủ công. Không cần phải khi nào bạn có thể làm cho trình biên dịch thực hiện công việc cho bạn.

+2

+1, không có lý do gì để xây dựng cây biểu thức theo cách thủ công khi trình biên dịch có thể làm điều đó cho bạn –

+1

@Thomas: Có, nhưng chúng tôi không thể thấy nơi 'left' và' right' đến từ đây ... họ ' có lẽ là loại 'Biểu thức', không phải' chuỗi'. –

+0

Có thể đây là cách tốt hơn nhưng thư viện mà tôi đang làm việc (https://github.com/ashokgelal/NetFilterFramework) đã được xây dựng bằng cách xây dựng một cây biểu thức theo cách thủ công. Bây giờ tôi chỉ cần thêm một cuộc gọi phương thức so sánh chuỗi nhưng có thể tôi cần phải tái cấu trúc/viết lại mọi thứ bằng cách sử dụng lambdas. – ashokgelal

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