Search code examples
c#scriptingcodedomsystem-codedom-compiler

C# Compiling User Supplied Code And Using


What I'm trying to do is allow a user to write a method in a textbox and have my code call that method. This will eventually be used in a demo applet for optimization given a goal function.

So I've been working with a sample console application but I'm having trouble. I've checked stack overflow and codeproject and other sources, and have got to the point where I can compile the code. But I'm lost at how to call it and only access a method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;

namespace CodeCompilerTest
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");

            CompilerParameters parameters = new CompilerParameters();
            //parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            //parameters.OutputAssembly = "Output.dll";

            string SourceString = @"
                                   using System;
                                   using System.Collections.Generic;
                                   using System.Text;

                                   namespace testone 
                                   {
                                        public class myclass
                                        {
                                            public double Main()
                                            {
                                                return testd(5,8);
                                            }

                                            public double testd(double a, double b)
                                            { 
                                                return a+b;
                                            } 
                                        } 
                                    }";

            CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, SourceString);

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError CompErr in results.Errors)
                {
                    Console.WriteLine("Line number " + CompErr.Line + ", Error Number: " + CompErr.ErrorNumber + ", '" + CompErr.ErrorText + ";");
                }
                Console.ReadLine();
            }

            Assembly mAssembly = results.CompiledAssembly;
            Type scripttype = mAssembly.GetType("myclass");
            Object rslt = new Object();
            Object[] argin = {5, 8};
            //rslt  = scripttype.GetMethod("Main").Invoke(null, null);
            rslt = scripttype.InvokeMember("Main", BindingFlags.InvokeMethod | BindingFlags.Public |BindingFlags.Static, null, null, null);
            Console.WriteLine(((double)rslt).ToString());
            Console.ReadLine();
        }
    }
}

I've tried different combinations on how to call the Invoke on the method and keep getting errors. What I want to be able to do is have the user define a function like this:

public double funcname(double x, double y)
{
    return x+y;
}

And then I could just call funcname directly. If this is not doable, I'll take what I can get at this point.

Any help or guidance would be appreciated. Thanks.


Solution

  • You need to include the namespace in the GetType call.
    (Or remove the namespace from the source)

    You may prefer to call GetTypes() and see all of the types defined in the assembly instead.