locked
How to convert string into System.Linq.Expressions.Expression in C#?

    Question

  • This code is works fine.
    Expression<Func<int, int>> fun = (i => (i + i) * 10 / 5 % 7);            

    But i want to get formula from console. So i do like 
             string formula = "i => (i + i) * 10 / 5 % 7";
             Expression<Func<int, int>> fun = (formula);            
    But i is not working bez, string can not be convert into Expression.
    My question is how can i convert?


    Monday, November 30, 2009 11:44 AM

Answers

  • Just look at what I wrote. The 10 lines starting at "using" are a string. You can concatenate strings. You can inject into that code whatever you want.

    CompilerResults results = provider.CompileAssemblyFromSource(new CompilerParameters(new[] { "System.Core.dll" }),
      @"using System;
        using System.Linq.Expressions;

        class foo
        {
            public static Expression<Func<int, int>> bar()
            {
                return " + myExpression + ";
            }
        }"
    );

    myExpression can be a variable, a method call like Console.ReadLine, or anything else you can concatenate to a string.

    If you inject directly an input from the user, it could be anything. You should check results.Errors before trying to call the foo.bar() method.
    • Marked as answer by DP_CHE Thursday, December 03, 2009 11:31 AM
    Tuesday, December 01, 2009 9:25 AM
  • Louis' code is correct, but perhaps DP_CHE didn't transcribe it correctly.

    Here's a complete program that incorporates it; try pasting this into a console app:

    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using Microsoft.CSharp;
    
    public class DemoProgram
    {
        public static void Main()
        {
            Dictionary<string, string> providerOptions = new Dictionary<string, string>();
            providerOptions.Add("CompilerVersion", "v3.5");
            CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
            
            CompilerResults results = provider.CompileAssemblyFromSource
            (
                new CompilerParameters(new[] { "System.Core.dll" }),
    @"using System;
    using System.Linq.Expressions;
    
    class foo
    {
        public static Expression<Func<int, int>> bar()
        {
            return (i => (i + i) * 10 / 5 % 7);
        }
    }"
            );
    
            Expression<Func<int, int>> expression = (Expression<Func<int, int>>)results.CompiledAssembly.GetType("foo").GetMethod("bar").Invoke(null, null);
            Func<int, int> func = expression.Compile();
    
            Console.WriteLine("func(101) = " + func(101));
        }
    }
    
    • Marked as answer by DP_CHE Thursday, December 03, 2009 11:31 AM
    Thursday, December 03, 2009 10:14 AM
  • Hi Louis, Matthew

    You code is right only.
    But i forget to put namespace Microsoft.CSharp

    Thanks 
    • Marked as answer by DP_CHE Thursday, December 03, 2009 11:32 AM
    Thursday, December 03, 2009 11:31 AM

All replies

  • There's no simple way to do this without writing a parser. 

    Use the static methods in the Expression class to start building the expression from the ground up.  This won't be simple, and will probably require a fair amount of recursion. 
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
    Monday, November 30, 2009 12:09 PM
    Moderator
  • Hi Thanks for the reply.
    Can you give any sample code.

    Monday, November 30, 2009 12:35 PM
  • A sample would be too complex for a forum post.  I'd suggest you start reading up on how to write a parser. 

    I posted a sample of how to parse and execute a simple bit of arithmetic here.  It's by no means comprehensive, and your application will be much more complex than this if you need to parse out an expression, but it's a start.  

    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
    Monday, November 30, 2009 1:35 PM
    Moderator
  • The parser already exists.

    Dictionary<string, string> providerOptions = new Dictionary<string, string>();
    providerOptions.Add("CompilerVersion", "v3.5");
    CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
    CompilerResults results = provider.CompileAssemblyFromSource(new CompilerParameters(new[] { "System.Core.dll" }),
      @"using System;
        using System.Linq.Expressions;
    
        class foo
        {
            public static Expression<Func<int, int>> bar()
            {
                return (i => (i + i) * 10 / 5 % 7);
            }
        }");
    Expression<Func<int, int>> fun = (Expression<Func<int, int>>)results.CompiledAssembly.GetType("foo").GetMethod("bar").Invoke(null, null);
    
    Monday, November 30, 2009 2:01 PM
  • Hi,
    This code will works fine only.
    Here you use like get the Expression from the method.
    In that bar() method, you just return the expression.
    there is no convert here.

    But if you try like this it wont work.
    public static Expression<Func<int, int>> bar()
            {
                return (Console.ReadLine());
            }
    I want like this. Bez i read the expression from the console only.
    Let me know any idea.
    Tuesday, December 01, 2009 5:07 AM
  • Just look at what I wrote. The 10 lines starting at "using" are a string. You can concatenate strings. You can inject into that code whatever you want.

    CompilerResults results = provider.CompileAssemblyFromSource(new CompilerParameters(new[] { "System.Core.dll" }),
      @"using System;
        using System.Linq.Expressions;

        class foo
        {
            public static Expression<Func<int, int>> bar()
            {
                return " + myExpression + ";
            }
        }"
    );

    myExpression can be a variable, a method call like Console.ReadLine, or anything else you can concatenate to a string.

    If you inject directly an input from the user, it could be anything. You should check results.Errors before trying to call the foo.bar() method.
    • Marked as answer by DP_CHE Thursday, December 03, 2009 11:31 AM
    Tuesday, December 01, 2009 9:25 AM
  • Hi,
    I try this but still i am getting error in CSharpCodeProvider.
    Can you please give some other sample?

    Thursday, December 03, 2009 5:11 AM
  • Which error do you get?
    Could you post the code you wrote?

    Thursday, December 03, 2009 8:33 AM
  • Louis' code is correct, but perhaps DP_CHE didn't transcribe it correctly.

    Here's a complete program that incorporates it; try pasting this into a console app:

    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using Microsoft.CSharp;
    
    public class DemoProgram
    {
        public static void Main()
        {
            Dictionary<string, string> providerOptions = new Dictionary<string, string>();
            providerOptions.Add("CompilerVersion", "v3.5");
            CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
            
            CompilerResults results = provider.CompileAssemblyFromSource
            (
                new CompilerParameters(new[] { "System.Core.dll" }),
    @"using System;
    using System.Linq.Expressions;
    
    class foo
    {
        public static Expression<Func<int, int>> bar()
        {
            return (i => (i + i) * 10 / 5 % 7);
        }
    }"
            );
    
            Expression<Func<int, int>> expression = (Expression<Func<int, int>>)results.CompiledAssembly.GetType("foo").GetMethod("bar").Invoke(null, null);
            Func<int, int> func = expression.Compile();
    
            Console.WriteLine("func(101) = " + func(101));
        }
    }
    
    • Marked as answer by DP_CHE Thursday, December 03, 2009 11:31 AM
    Thursday, December 03, 2009 10:14 AM
  • Hi Louis, Matthew

    You code is right only.
    But i forget to put namespace Microsoft.CSharp

    Thanks 
    • Marked as answer by DP_CHE Thursday, December 03, 2009 11:32 AM
    Thursday, December 03, 2009 11:31 AM
  • Hi,

     

    I know this is for winForms, but is it possible for c# for web?

    Friday, April 15, 2011 5:57 PM
  • Yes, it is.
    Friday, April 15, 2011 6:04 PM