A variable is injected into Mono. Evaluator.CSharp (runtime compiling a LINQ query from string)

c# expression-trees linq

Question

To generate code, I'm use the Mono.CSharp library. I was able to get Mono.CSharp evaluating successfully on the Microsoft CLR after answering another question on SO (http://stackoverflow.com/questions/3407318/mono-compiler-as-a-service-mcs).

In order to increase flexibility in my program, I'd want to provide the user the ability to supply a LINQ query as a string that is parsed and hits the database when performed.

Given this fundamental piece of code:

IQueryable<Contact> contacts = GetContacts();
string query = "from contact in contacts
                where contact.Name == \"name\"
                select contact";
var queryableResult = Mono.CSharp.Evaluator.Evaluate(query);

What is the best way to "inject" the contacts variable into the Mono.CSharp.Evaluator such that it is evaluated as part of the query? Am I approaching this correctly? Either the generated Expression or the IQueryable from the 'query' string is what I ultimately require.

1
4
9/24/2010 2:34:52 PM

Accepted Answer

You have a few choices, in my opinion:

  1. If you're using string-based code, use static or ThreadStatic variables to share data with the caller:

    namespace MyNs
    {
      public class MyClass
      {
     [ThreadStatic] // thread static so the data is specific to the calling thread
     public static string MyEnumerableVariable;
    
    
     public void DoSomething() 
     {
          Evaluator.ReferenceAssembly(Assembly.GetExecutingAssembly());
          Evaluator.Run("using MyNs;")
          // run the dynamic code
          var s = @"return (from contact in MyNs.MyClass.MyEnumerableVariable where contact.Name == ""John"" select contact).ToList();";
          Evaluator.Evaluate(s);
     }
    

    } }

  2. In response to your string code, provide a delegate:

    
     public void DoSomething() 
     {
    
    

    // run the dynamic code var s = @"return new Func<string, IQueryable<MyNs.Model.Contact>, IList>((s,q) => (from contact in q where contact.Name == s select contact).ToList());"; var func = (Func<string, IQueryable<MyNs.Model.Contact>, IList>)Evaluator.Evaluate(s); var result = func("John", myQueryableOfContactsFromNHibernate);

    }

  3. Decide to go all out.

string query = string.Format(
@"using (var dc = new DataContext()) 
{
  return (from contact in dc.Contacts where contact.Name == ""{0}"" select contact).ToList();
}", "John");

var result = Mono.CSharp.Evaluator.Evaluate(query);

4
9/24/2010 7:33:38 PM

Popular Answer

You may be able to design a delegate that accepts using the Mono compiler, however I haven't tried it.IQueryable<Contract> returns the filtered query with the given parameter. the following

IQueryable<Contact> contacts = GetContacts(); 
string query = "new Func<IQueryable<Contact>, IQueryable<Contact>>(contracts =>
                  from contact in contacts 
                  where contact.Name == \"name\" 
                  select contact)"; 
var res = Mono.CSharp.Evaluator.Evaluate(query); 

then all you have to do is cast.res to a suitableFunc<,> To obtain the result, type and use it.



Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow