2009-01-27 41 views
6

Ý tưởng cơ bản là lấy một chuỗi và đánh giá nó dựa vào Tệp XML (hoặc bất kỳ nhà cung cấp LINQed nào)Có thể đánh giá một chuỗi chứa LINQ động/thời gian chạy hợp lệ không?

Tôi tìm thấy điều này LINQ Dynamic Query Library. Chỉ cần có một cái nhìn lướt qua tại tài liệu đó là một trang duy nhất trong gói tải xuống. Điều này có vẻ là thêm các phương thức mở rộng để tham số hóa các phần của truy vấn LINQ. Có ai biết nếu điều này không đánh giá năng động?

Có cách nào để thực hiện (giả sử có một số cách để đưa lớp vào với Dữ liệu từ Tệp XML) không?

ClassFromWishfulThinking.Evaluate(sLinqQuery); 
+0

Tôi đã bỏ phiếu cho câu hỏi của bạn, chỉ vì nó ở -1 khi tôi xem nó. Không hoàn toàn chắc chắn lý do tại sao ai đó sẽ bỏ phiếu cho câu hỏi của bạn ... – GregD

Trả lời

3

Nó phải có thể bởi vì Linqpad hiện nó!

Nhìn vào how it works page hơi bị bẻ cong, và tôi không chắc đây là điều bạn muốn làm với mã sản xuất trừ khi bạn thực sự không thể tránh được.

Không có phương pháp khung nào chỉ làm những gì bạn muốn, tôi có thể nói rằng với mức độ tin cậy khá cao vì cách thức hoạt động của .net. Bạn phải gọi trình biên dịch bằng cách sử dụng csharpcodeprovider như LinqPad.

Bạn có thể thay đổi Thư viện truy vấn động LINQ để thực hiện những gì bạn cần.

+0

Nó không phải là mã sản xuất .. thay vì cố gắng làm một phiên bản đơn giản của Linqpad .. nhưng chống lại XML thay vì SQL. – Gishu

0

Phần lớn LinqToXml được điều khiển bởi chuỗi. Ví dụ: Elements extension method sẽ lấy một chuỗi và tìm tất cả các phần tử con có tên đó.

Nếu truy vấn của bạn bắt đầu dưới dạng một chuỗi (và không phải là phương thức gọi trên Truy vấn/đếm được), thì đó không thực sự là truy vấn LINQ - mà là một thứ khác. Có thể XPath có thể hữu ích.

2

Tôi đã có mã này trong VB để đánh giá mã chứa trong một chuỗi tại thời gian chạy ... bạn sẽ cần dịch nó sang C#, nhưng không có lý do gì bạn không thể chuyển vào chuỗi chứa LINQ biểu hiện. Bạn sẽ cần phải sửa đổi FuncString một chút để cho phép sử dụng LINQ vì tôi chỉ tham chiếu System.Math. Tôi sử dụng nó để đánh giá các biểu thức (chủ yếu là toán học) khi chạy, nhưng tôi tưởng tượng nó có thể được sửa đổi/mở rộng để đánh giá khá nhiều bất cứ điều gì trong khuôn khổ NET ...

Function Evaluate(ByVal Expression As String, ByVal Args() As Object) As Object 

    If Expression.Length > 0 Then 

     'Replace each parameter in the calculation expression with the correct values 
     Dim MatchStr = "{(\d+)}" 
     Dim oMatches = Regex.Matches(Expression, MatchStr) 
     If oMatches.Count > 0 Then 
      Dim DistinctCount = (From m In oMatches _ 
           Select m.Value).Distinct.Count 
      If DistinctCount = Args.Length Then 
       For i = 0 To Args.Length - 1 
        Expression = Expression.Replace("{" & i & "}", Args(i)) 
       Next 
      Else 
       Throw New ArgumentException("Invalid number of parameters passed") 
      End If 
     End If 

     Dim FuncName As String = "Eval" & Guid.NewGuid.ToString("N") 
     Dim FuncString As String = "Imports System.Math" & vbCrLf & _ 
            "Namespace EvaluatorLibrary" & vbCrLf & _ 
            " Class Evaluators" & vbCrLf & _ 
            " Public Shared Function " & FuncName & "() As Double" & vbCrLf & _ 
            "  " & Expression & vbCrLf & _ 
            " End Function" & vbCrLf & _ 
            " End Class" & vbCrLf & _ 
            "End Namespace" 

     'Tell the compiler what language was used 
     Dim CodeProvider As CodeDomProvider = CodeDomProvider.CreateProvider("VB") 

     'Set up our compiler options... 
     Dim CompilerOptions As New CompilerParameters() 
     With CompilerOptions 
      .ReferencedAssemblies.Add("System.dll") 
      .GenerateInMemory = True 
      .TreatWarningsAsErrors = True 
     End With 

     'Compile the code that is to be evaluated 
     Dim Results As CompilerResults = _ 
      CodeProvider.CompileAssemblyFromSource(CompilerOptions, FuncString) 

     'Check there were no errors... 
     If Results.Errors.Count > 0 Then 
     Else 
      'Run the code and return the value... 
      Dim dynamicType As Type = Results.CompiledAssembly.GetType("EvaluatorLibrary.Evaluators") 
      Dim methodInfo As MethodInfo = dynamicType.GetMethod(FuncName) 
      Return methodInfo.Invoke(Nothing, Nothing) 
     End If 

    Else 
     Return 0 

    End If 

    Return 0 

End Function 

Sub Main() 
    'In a real application, this string would be loaded from a database 
    'it would be stored by some calculation administrator... 
    Dim Expr As String = " If ({0} < 20000) Then" & vbCrLf & _ 
         " Return Max(15, Min(75,0.12*{0}))" & vbCrLf & _ 
         " Else" & vbCrLf & _ 
         " Return Max(75,0.05*{0})" & vbCrLf & _ 
         " End If" 

    Dim Args As New List(Of String) 
    While True 
     'This value would be loaded from some data interpreter for inclusion 
     'in the calculation... 
     Dim Val As String = Console.ReadLine 
     Args.Clear() 
     If IsNumeric(Val) Then 
      Args.Add(Val) 
      Dim dblOut As Object = Evaluate(Expr, Args.ToArray) 
      Console.WriteLine(dblOut) 
     Else 
      Exit While 
     End If 
    End While 

End Sub 

Không có lý do bạn không thể sửa đổi định nghĩa hàm một chút để nó có thể hoạt động như một phần mở rộng của chuỗi để cho phép bạn gọi nó như vậy:

Dim LinqString = "from c in myLinqData where c.SomeField.Equals(""somevalue"") select c" 
Dim output = LinqString.Evaluate 
Các vấn đề liên quan