2011-05-12 6 views
1

사용자가 텍스트 상자에 메서드를 작성하고 해당 메서드를 호출하도록 코드를 만들 수 있습니다. 이것은 목표 함수가 주어진 최적화를 위해 데모 애플릿에서 결국 사용됩니다.C# 사용자 제공 코드 컴파일 및 사용

그래서 샘플 콘솔 응용 프로그램으로 작업했지만 문제가 있습니다. 나는 스택 오버플로와 codeproject 및 기타 소스를 점검하고 코드를 컴파일 할 수있는 지점에 도달했습니다. 그러나 나는 그것을 호출하는 방법에 길을 잃고 오직 방법에 접근한다.

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

메서드에 대한 호출을 호출하고 오류를 계속받는 방법에 대해 여러 가지 조합을 시도했습니다.

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

을 그리고 난 그냥 직접 funcname에를 호출 할 수 있습니다 은 내가 할 수 있기를 원하는 것은 사용자가이 같은 함수를 정의해야합니다. 이것이 가능하지 않다면, 지금 내가 얻을 수있는 것을 취할 것입니다.

도움이나 조언을 제공해 주시면 감사하겠습니다. 감사합니다. .

답변

1

GetType 호출에 네임 스페이스를 포함해야합니다.

GetTypes()을 호출하고 대신 어셈블리에 정의 된 모든 유형을 볼 수 있습니다.

+0

작동하지 않았기 때문에
또한 나는 GetTypes()[0]을 사용했다. "testd (5,8)"와 같이 호출하는 방법을 알고 있습니까? 궁극적 인 희망은 dll에 대한 대리자로서 사용자가 제공하는 함수입니다. –

+0

또 다른 유용한 리소스는 다음과 같습니다. http://stackoverflow.com/questions/1698870/accessing-class-and-function-after-compiling-compiledassembly –

+0

@Tim : GetTypes()를 호출하고 당신이 찾고있는 기능을 가진 타입. – SLaks

1

나는 귀하의 요청에 직접적으로 관련이없는이 문서가 당신이 사용하는 인터페이스 아마 아래 http://www.codeproject.com/Articles/26312/Dynamic-Code-Integration-with-CodeDom

을 통해 방법을 직접 액세스하는 데 도움이 될 것입니다 생각하지만, 난 당신의 인스턴스를 생성 활성제를 사용할 필요가 있다고 생각 클래스는 testd 메서드로 호출 할 수 있습니다. 정의 된 코드에는 객체가 없으며 클래스 정의 만 있습니다. GetType() 그래서 그 날이 호출 방법을 사용하여 함수를 호출 할 수 있습니다 나를

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