Question

Ce que j'essaie de faire, c'est permettre à un utilisateur d'écrire une méthode dans une zone de texte et de faire appeler cette méthode. Cela sera finalement utilisé dans une applet de démonstration pour l'optimisation compte tenu d'une fonction d'objectif.

J'ai donc travaillé avec un exemple d'application de console mais j'ai des problèmes. J'ai vérifié Stack Overflow et CodeProject et d'autres sources, et j'ai atteint le point où je peux compiler le code. Mais je suis perdu sur la façon de l'appeler et d'accès uniquement à une méthode.

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();
        }
    }
}

J'ai essayé différentes combinaisons sur la façon d'appeler l'invocation sur la méthode et de continuer à obtenir des erreurs. Ce que je veux pouvoir faire, c'est que l'utilisateur définisse une fonction comme ceci:

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

Et puis je pourrais simplement appeler Funcname directement. Si ce n'est pas faisable, je vais prendre ce que je peux obtenir à ce stade.

Toute aide ou guidage serait appréciée. Merci.

Était-ce utile?

La solution

Vous devez inclure l'espace de noms dans le GetType appel.
(Ou supprimer l'espace de noms de la source)

Vous préférez peut-être appeler GetTypes() et voir tous les types définis dans l'assemblage à la place.

Autres conseils

Je crois que cet article vous aidera à accéder directement à la méthode en utilisant des interfaceshttp://www.codeproject.com/articles/26312/dynamic-code-integration-with-codedom

Peut-être que ce qui précède n'est pas pertinent directement pour votre demande, mais je pense que vous devez utiliser Activator pour créer une instance de la classe afin que vous puissiez appeler le testd Méthode Je veux dire que votre code défini n'a pas d'objet, juste une définition de classe.
J'ai aussi utilisé GetTypes()[0] car GetType() n'a pas fonctionné pour moi

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();
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top