基本思想是取一個字符串並對照XML文件(或任何LINQed提供者)進行評估。是否可以在運行時動態/評估包含有效LINQ的字符串?
我發現這個LINQ Dynamic Query Library。只是粗略瀏覽了下載包中單個頁面的文檔。這似乎是添加了擴展方法來參數化部分LINQ查詢。有誰知道這是否做動態評估?
有沒有什麼辦法可以做(假設有一些方法可以用XML文件中的數據對類進行播種)?
ClassFromWishfulThinking.Evaluate(sLinqQuery);
基本思想是取一個字符串並對照XML文件(或任何LINQed提供者)進行評估。是否可以在運行時動態/評估包含有效LINQ的字符串?
我發現這個LINQ Dynamic Query Library。只是粗略瀏覽了下載包中單個頁面的文檔。這似乎是添加了擴展方法來參數化部分LINQ查詢。有誰知道這是否做動態評估?
有沒有什麼辦法可以做(假設有一些方法可以用XML文件中的數據對類進行播種)?
ClassFromWishfulThinking.Evaluate(sLinqQuery);
這一定是可能的,因爲Linqpad做到了!
看着how it works page是有點頭腦彎曲,我不確定這是你想要做的生產代碼,除非你真的無法避免它。
沒有框架方法只是做你想做的事情,我可以說由於.NET的工作方式而具有相當高的信心。您必須使用LinqPad所使用的csharpcodeprovider來調用編譯器。
您可能可以更改Linq動態查詢庫來執行您所需的操作。
這不是生產代碼..而是試圖做一個簡單版本的Linqpad ..但是反對XML而不是SQL。 – Gishu 2009-01-27 16:46:07
很多LinqToXml都是由字符串驅動的。例如,Elements extension method將採用一個字符串並查找具有該名稱的所有子元素。
如果您的查詢以字符串開頭(而不是Queryable/Enumerable上的方法調用),那麼它並不是一個真正的linq查詢 - 不過是別的。也許XPath可以提供幫助。
我已經在VB中使用這段代碼來評估運行時字符串中包含的代碼......您需要將它轉換爲C#,但沒有理由不能傳遞包含LINQ的字符串表達。您需要稍微修改FuncString以允許使用LINQ,因爲我只引用System.Math。我用它在運行時(大多是數學)表現的評價,但我想它可以修改/擴展到評估在.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
沒有理由你不能稍微修改函數定義,以便它可以作爲字符串的擴展名,以便讓您像這樣調用它:
Dim LinqString = "from c in myLinqData where c.SomeField.Equals(""somevalue"") select c"
Dim output = LinqString.Evaluate
我投了你的問題,僅僅因爲它在我看到它時坐在-1。不太清楚爲什麼有人會投下你的問題... – GregD 2009-01-27 14:59:04