Pregunta

Lo que estoy tratando de hacer es permitir a un usuario escribir un método en un cuadro de texto y tengo mi código de llamar a ese método.Esto va a llegar a ser utilizado en una demostración de subprograma para la optimización dada una función objetivo.

Así que he estado trabajando con un ejemplo de aplicación de consola, pero estoy teniendo problemas.He comprobado desbordamiento de pila y codeproject y otras fuentes, y han llegado al punto donde puedo compilar el código.Pero estoy perdido en cómo llamar a ella y sólo tener acceso a un método.

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

He probado diferentes combinaciones sobre cómo llamar a Invocar el método y seguir recibiendo errores.Lo que quiero ser capaz de hacer es que el usuario defina una función como esta:

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

Y entonces yo podría llamar funcname directamente.Si esto no es factible, me quedo con lo que puedo llegar a este punto.

Cualquier ayuda u orientación, se agradecería.Gracias.

¿Fue útil?

Solución

Es necesario incluir el espacio de nombres en el GetType de la llamada.
(O quitar el espacio de nombres de la fuente)

Usted puede preferir llamar GetTypes() y ver todos los tipos definidos en el ensamblaje en su lugar.

Otros consejos

Creo que este artículo le ayudará a tener acceso al método directamente a través de la utilización de interfaces http://www.codeproject.com/Articles/26312/Dynamic-Code-Integration-with-CodeDom

Tal vez el de abajo no es relevante directamente a su petición, pero creo que usted necesita para usar el Activador para crear una instancia de la clase, de modo que usted puede llamar a la testd método Me refiero a su código definido no tiene objeto, tal definición de la clase.
También he utilizado GetTypes()[0] porque GetType() no funciona para mí

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();
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top