Is it possible to evaluate a string containing a valid LINQ dynamically / at runtime?

The basic idea is to take a string and evaluate it against an XML file (or any LINQed provider)

I found this LINQ Dynamic Query Library . It was just a quick look at the documentation, which is one page in the download kit. This seems to be adding extension methods to parameterize parts of the LINQ query. Does anyone know if this makes a dynamic assessment?

Is there any way to do this (assuming there is some way to seed a class with data from an XML file)?

ClassFromWishfulThinking.Evaluate(sLinqQuery); 
+6
source share
3 answers

It should be possible because Linqpad does it!

Looking at how it works on a page is a bit of a mind, and I'm not sure if this is what you would like to do with production code, if you really couldn’t avoid it.

There is no framework method that just does what you want, I can say that with a fairly high degree of confidence because of how .NET works. You must invoke the compiler using csharpcodeprovider , as LinqPad does.

You may be able to modify the Linq dynamic query library to do what you need.

+3
source share

I have this code in VB to evaluate the code contained in a string at runtime ... you need to translate it to C #, but there is no reason why you could not just pass in a string containing a LINQ expression, you will need a little modify FuncString to use LINQ as I am only referring to System.Math. I use it to evaluate (mostly mathematical) expressions at runtime, but I assume that it can be modified / extended to evaluate almost everything in the .NET framework ...

 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 

There is no reason why you could not change the definition of a function so that it can function as a string extension, so you can call it like this:

 Dim LinqString = "from c in myLinqData where c.SomeField.Equals(""somevalue"") select c" Dim output = LinqString.Evaluate 
+2
source share

Most LinqToXml is string driven anyway. For example, the Element Extension Method will take a string and find all child elements with this name.

If your query starts as a string (and not as method calls in Queryable / Enumerable), then this is not really a linq query, but something else. Perhaps XPath can help.

0
source share

All Articles