Accepted answer

it must be possible because linqpad does it!

looking at the how it works page is a bit mind bending, and i'm not sure this is something you would want to do with production code unless 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 have to call the compiler using the csharpcodeprovider as linqpad does.

you might be able to change the linq dynamic query library to do what you need.


much of linqtoxml is driven by strings anyway. for example, the elements extension method will take a string and find all the child elements with that name.

if your query starts as a string (and not as method calls on queryable/enumerable), then it isn't really a linq query - but something else. maybe xpath can help.


i've got this code in vb to evaluate code contained in a string at runtime... you'll need to translate it to c#, but there's no reason you couldn't just pass in a string containing a linq expression. you'd need to modify funcstring slightly to allow for the use of linq as i only reference system.math. i use it for evaluation of (mostly mathematical) expressions at runtime, but i imagine it could be modified/expanded to evaluate pretty much anything 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))
                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
            .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
            '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

        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
        if isnumeric(val) then
            dim dblout as object = evaluate(expr, args.toarray)
            exit while
        end if
    end while

end sub

there's no reason you couldn't modify the function definition slightly so that it could function as an extension of string to allow you to call it like so:

dim linqstring = "from c in mylinqdata where c.somefield.equals(""somevalue"") select c"
dim output = linqstring.evaluate

Related Query

More Query from same tag