문제

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.

도움이 되었습니까?

해결책

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.

다른 팁

I believe this article will help you to access the method directly through using interfaces http://www.codeproject.com/Articles/26312/Dynamic-Code-Integration-with-CodeDom

Maybe the below is not relevant directly to your request, but I believe that you need to use Activator to create an instance of the class so you can call the testd method I mean your code defined has no object, just class definition.
Also I used GetTypes()[0] because GetType() didn't work for me

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 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.GetTypes()[0];
            Object myObject = Activator.CreateInstance(scripttype);
            double  rsltd = 0.0;
            Object[] argin = { 5.0, 8.0 };
            rsltd  =(double) scripttype.GetMethod("testd").Invoke(myObject,argin);
          //  object rslt = new object();
           // rslt = scripttype.InvokeMember("testd", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, null);
       Console.WriteLine(rsltd.ToString());
       Console.ReadLine();
        }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top