0

I have a query that I need to create as a string, transport over WCF and and then compile into LINQ at the other end. The reason that I'm not transporting the actual LINQ query itself over WCF is because the method which produces the query should have no knowledge of the source type used in the query (i.e. no dependencies).

Here's the problem then: I pass my query over the wire as a string, have CSharpCodeProvider try and compile it and it can't find the data source referenced in the query (serverSource in the code below). How do I go about creating this query and compiling with CSharpCodeProvider?

var newQuery =  @"using System.Linq;" +
                                "public class SIQuery" +
                                "{" +
                                    "public static void Main(string[] args)" +
                                    "{" +
                                        "var siQuery = from e in " + serverSource + " where e % 5 == 0 select e;" +
                                    "}" +
                                "}";

I've tried defining serverSource before compiling at runtime (var serverSource = application.GetStreamable<long>("serverSource"); ) but this doesn't have any affect on the outcome (the fact that serverSource can't be found).

Thanks in advance!

user2766816
  • 21
  • 1
  • 3
  • This seems like a pretty terrible thing to need to do. Instead just pass some collection of numbers using WCF, which is easy enough to do, and then just define the query in static code. – Servy Sep 30 '13 at 20:02
  • Servy: what are you referring to when mentioning "some collection of numbers"? I'm trying to somehow get the CSharpCodeProvider to recognise my source, which is defined in another application and constantly outputs data. – user2766816 Sep 30 '13 at 20:38
  • 1
    And the other application won't have access to that source; knowing the name of a variable doesn't mean much if you can't access it. Instead send the value of the variable and act on *that*. If it changes, then you need to be querying across the network for the value of the variable each time you want to access it. – Servy Sep 30 '13 at 20:39
  • So when the name of the variable and the query come from the WCF pipeline into the server (either explicity or through using regex on the query), the server will look up the source using this name. This can then be used by the server to insert the correct source into the query. I don't actually have access to the value of the variable before sending across WCF as it resides elsewhere, which is the whole reason why I'm looking to create a query as a string and have C# compile it at runtime. I hope this all makes sense! – user2766816 Sep 30 '13 at 20:58
  • If the value of that variable is defined on the client then that variable name means nothing; it isn't associated with a value. If it *is* defined on the server then it would need to be of a finite number of possibilities known at compile time; create an `Enum` or something for them all and have a `case` statement to determine the source. – Servy Sep 30 '13 at 21:00
  • The variable is defined on the server. As for finite possibilities, this isn't an option. Some background: A client can publish any new source to the server at runtime, and give it any name. A user might then use some UI to select one of the available sources from the server and write their own LINQ query against this source. Hence the reason why we can't define any Enum or otherwise at compile time - the name of the source alone needs to suffice when actually coming to retrieve said source. – user2766816 Sep 30 '13 at 21:06

1 Answers1

0

Potentially you could use the CompilerParameters to add an Embedded Resource (the parameter will take the path of a resx file).

You'll have to drop the concatenation and call a global variable to access it from the Emit code, but it should work.

Non-working example:

cp.EmbeddedResources.Add("resource_files.resx"); // File local to the actual code, not the emitting code.
...
string code = @"
using System.Linq;

namespace CoolThing
{
    public class SIQuery
    {
        public static void Main(string[] args)
        {
            var siQuery = from e in Resources.resource_files.serverSource
                          where e % 5 == 0 select e;
        }
    }

}";