2012-03-23 56 views
7

Tôi có một situtaiton nơi tôi đọc logic kinh doanh và thay thế các biến với giá trị thực tế và sau đó tôi cần phải đánh giá nó để có được kết quả. Tôi hiện đang sử dụng bcParser để làm điều đó và nó hoạt động tốt cho tất cả các logic được viết như định dạng excel.Có thể tạo một cây biểu thức cho các câu lệnh động không?

Bóng cong được ném vào tôi là, nếu điều kiện sẽ không giống như excel if(cond, true, false) thay vì nó sẽ giống như C# nơi if (cond) { true; } else { false;}, điều này có ý nghĩa hơn và dễ bảo trì. Vì tôi thay thế tất cả các biến với giá trị trước khi bàn tay, tất cả những gì tôi phải làm là đánh giá nó. Hiện tại tôi đang giải quyết vấn đề này bằng cách xuất logic sang các phương thức C# và sử dụng sự phản chiếu mà tôi đang đánh giá nó và nó cũng hoạt động.

Tôi tự hỏi là có bất kỳ tùy chọn nào khác, tôi không muốn viết mã cho từng điều kiện và muốn đánh giá nó trên thời gian chạy. Tôi đã tự hỏi nếu tôi có thể tạo một trình phân tích cú pháp của một số loại và gọi C# biểu thức bản địa đánh giá và thực hiện tính toán. Tôi đã không hiểu những cây xuất hiện, dường như có thể với cách tiếp cận đó. trước khi tôi đến đó, tôi muốn biết là nó có thể xảy ra không? Cảm ơn,

+3

Cây biểu thức sẽ không giúp bạn phân tích cú pháp chuỗi. Bạn có thể muốn xem [CodeDom] (http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx) hoặc [Rosalyn] (http://msdn.microsoft.com/en-us/roslyn). –

Trả lời

5

Có!

Điều quan trọng là sử dụng không gian tên System.Linq.Expressions. Bạn có thể xây dựng một cây biểu thức theo lập trình, hoặc trong mã của bạn hoặc bằng cách sửa đổi trình phân tích cú pháp của bạn, sau đó biên dịch nó thành một Delegate. API này biên dịch Delegate bên trong của một DynamicAssembly có nghĩa là các biểu thức đã biên dịch của bạn có thể được tải xuống từ bộ nhớ bởi bộ thu gom rác khi bạn hoàn toàn coi trọng chúng.

Dưới đây là một ví dụ rất đơn giản:

var b = true; 
Func<bool> condition =() => b; 
Action trueExpression =() => { Console.WriteLine(true); }; 
Action falseExpression =() => { Console.WriteLine(false); }; 

var e = Expression.Condition(
    Expression.Invoke(Expression.Constant(condition)), 
    Expression.Invoke(Expression.Constant(trueExpression)), 
    Expression.Invoke(Expression.Constant(falseExpression))); 

var λ = Expression.Lambda(e).Compile(); 

b = true; 
λ.DynamicInvoke(); 

b = false; 
λ.DynamicInvoke(); 

này tạo ra kết quả:

True 
False 

Bước nơi biểu thức được biên soạn thành một Lambda có thể là một hiệu suất đáng kể hit, bạn sẽ muốn để đưa ra một chiến lược bộ nhớ đệm cho lambdas đã biên dịch của bạn. Nó cũng có giá trị nó mặc dù, gọi lambda biên dịch bằng cách sử dụng DynamicInvoke là rất nhanh. Hầu như nhanh như thể bạn đã biên dịch trước nó. Kỹ thuật này nhanh hơn đáng kể so với việc sử dụng tạo mã CodeDom (yêu cầu toàn bộ quá trình khác để thực hiện quá trình biên dịch) và nó có lợi ích chính là tạo ra các assembly không thể nạp được.

Hạn chế duy nhất cho điều này là bạn không thể tạo các loại với API này. Bạn phải giới hạn bản thân với các biểu thức và câu lệnh. Nó khá mạnh mẽ tuy nhiên, đây là sự can đảm ma thuật của DLR.

+1

Bạn nhận được biểu tượng lambda như thế nào? Muốn! – usr

+1

Sao chép dán! Nó chỉ là một nhân vật unicode. Có hiệu lực trong C#. –

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