2012-01-13 41 views
6

thể trùng lặp:
Is there an easy way to parse a (lambda expression) string into an Action delegate?Tạo biểu thức lambda từ một chuỗi

Tôi muốn để lưu trữ các biểu thức lambda như các chuỗi trong một tập tin cấu hình và khi chạy tự động tải những chuỗi thành biểu thức lambda trong C#. Mục tiêu của tôi là cấu hình và tiêm các quy tắc. Bất kỳ tiện ích nào có sẵn để tạo các biểu thức lambda từ một chuỗi?

Có bất kỳ giải pháp trọng lượng nhẹ nào khác cho cùng một mục tiêu không?

+0

Có thể trùng lặp? [http://stackoverflow.com/questions/714799/is-there-an-easy-way-to-parse-a-lambda-expression-string-into-an-action-delega](http://stackoverflow. com/questions/714799/is-there-an-easy-way-to-parse-a-lambda-biểu-chuỗi-thành-một-hành động-delega) – MNIK

+0

Có thể có liên quan: http://stackoverflow.com/questions/ 8327831/có thể-net-được-phân tích cú pháp-và-đánh giá-tại-thời gian chạy/8328096 # 8328096 – sehe

+0

Bỏ phiếu để đóng. Lưu ý phụ: xem xét nhiều ngôn ngữ thân thiện với kịch bản hơn cho LUA logic của bạn (http://stackoverflow.com/questions/1283641/lua-wrapper-for-c), IronPython, –

Trả lời

4

Nếu bạn biết loại biểu thức trước thời hạn, thì bạn có thể biên dịch chúng thành một phần của một lớp rồi kéo chúng ra khỏi tập hợp kết quả.

Dưới đây là ví dụ thực hiện (với các biểu thức lấy một chuỗi và trả về một bool) và chạy các quy tắc kết quả.

Với các nội dung của c: \ temp \ rules.txt bị này:

file => file.Length == 0 
file => System.IO.Path.GetExtension(file) == ".txt" 
file => file == null 

Sau đó, kết quả đầu ra là thế này:

Rules found in file: 
file => file.Length == 0, 
file => System.IO.Path.GetExtension(file) == ".txt", 
file => file == null, 

Checking rule file => (file.Length == 0) against input c:\temp\rules.txt: False 
Checking rule file => (GetExtension(file) == ".txt") against input c:\temp\rules.txt: True 
Checking rule file => (file == null) against input c:\temp\rules.txt: False 

Nguồn:

using System; 
using System.Xml.Linq; 
using System.Linq; 
using System.IO; 
using Microsoft.CSharp; 
using System.CodeDom.Compiler; 
using System.Reflection; 
using System.Linq.Expressions; 

class Program 
{ 
    private const string classTemplate = @" 
      using System; 
      using System.Linq.Expressions; 

      public static class RulesConfiguration 
      {{ 
       private static Expression<Func<string, bool>>[] rules = new Expression<Func<string, bool>>[] 
       {{ 
        {0} 
       }}; 

       public static Expression<Func<string, bool>>[] Rules {{ get {{ return rules; }} }} 
      }} 
     "; 

    static void Main(string[] args) 
    { 
     var filePath = @"c:\temp\rules.txt"; 
     var fileContents = File.ReadAllLines(filePath); 

     // add commas to the expressions so they can compile as part of the array 
     var joined = String.Join("," + Environment.NewLine, fileContents); 

     Console.WriteLine("Rules found in file: \n{0}", joined); 

     var classSource = String.Format(classTemplate, joined); 

     var assembly = CompileAssembly(classSource); 

     var rules = GetExpressionsFromAssembly(assembly); 

     foreach (var rule in rules) 
     { 
      var compiledToFunc = rule.Compile(); 
      Console.WriteLine("Checking rule {0} against input {1}: {2}", rule, filePath, compiledToFunc(filePath)); 
     } 
    } 

    static Expression<Func<string, bool>>[] GetExpressionsFromAssembly(Assembly assembly) 
    { 
     var type = assembly.GetTypes().Single(); 
     var property = type.GetProperties().Single(); 
     var propertyValue = property.GetValue(null, null); 
     return propertyValue as Expression<Func<string, bool>>[]; 
    } 

    static Assembly CompileAssembly(string source) 
    { 
     var compilerParameters = new CompilerParameters() 
     { 
      GenerateExecutable = false, 
      GenerateInMemory = true, 
      ReferencedAssemblies = 
      { 
       "System.Core.dll" // needed for linq + expressions to compile 
      }, 
     }; 
     var compileProvider = new CSharpCodeProvider(); 
     var results = compileProvider.CompileAssemblyFromSource(compilerParameters, source); 
     if (results.Errors.HasErrors) 
     { 
      Console.Error.WriteLine("{0} errors during compilation of rules", results.Errors.Count); 
      foreach (CompilerError error in results.Errors) 
      { 
       Console.Error.WriteLine(error.ErrorText); 
      } 
      throw new InvalidOperationException("Broken rules configuration, please fix"); 
     } 
     var assembly = results.CompiledAssembly; 
     return assembly; 
    } 
} 
2

Có xem Dynamic Linq. Đó là một bài cũ nhưng luôn hữu ích.

+1

Cuộc gọi tốt - bạn có thể cài đặt gói nuget DynamicQuery (tên là "API biểu thức động") - xem http://nuget.org/packages/DynamicQuery –

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