2013-02-27 2 views
1

Я компилирую код на лету, используя System.CodeDom.Compiler. Все внутри скомпилированного источника работает хорошо, независимо от того, что я вкладываю в этот источник. Я знаю, как назвать свои функции:Вызвать обратный вызов «хозяина» из «скомпилированной сборки из источника»

o = results.CompiledAssembly.CreateInstance("Foo.Bar"); 
MethodInfo mi = o.GetType().GetMethod("SayHello"); 
mi.Invoke(o, null); 

Но, допустим, я использую WebClient, чтобы получить строку, асинхронно с помощью WebClient.DownloadStringAsync. Или любой другой контекст, где я хочу, чтобы мой скомпилированный источник сообщил хосту: «Эй, у меня есть хорошая строка, готовая для вас». Например, я использовал WebBrowser. В принципе, я знаю, как иметь дело с каждым из двух экземпляров: моя программа хостинга и скомпилированная программа, но я хочу, чтобы моя скомпилированная программа связывалась с хостом. Кстати, я не супер-экспериментированный программист, поэтому мне не приходит очевидного метода.

Что я пробовал:

1. Мне действительно не нужно пытаться, потому что это сработает, но я мог бы использовать таймер, читающий стек строк или очередь задач внутри скомпилированного источника, но цель моего приложения состоит в том, чтобы иметь + 60 скриптов, способных выполнять контрольные задачи , а не непрерывные фоновые процессы, поэтому он не будет эффективен для CPU.

2. Я прошел обработчик скомпилированного источника, как если бы это было в приложении хостинг:

//In the hosting app 
    MethodInfo mi2 = o.GetType().GetMethod("attachCallbackToHost"); 
    mi2.Invoke(o2, new object[] { new WebBrowserNavigatedEventHandler (wb_navigated) }); 

    //... And the handler 
    public static void wb_navigated(object sender, WebBrowserNavigatedEventArgs e) 
    {    
     string browserHtmlFromCompiledSource = ((WebBrowser)sender).DocumentText; 
     MessageBox.Show(browserHtmlFromCompiledSource); 
    } 

    // Plain text from the compiled source code 
    public void attachCallbackToHost(WebBrowserNavigatedEventHandler handlerFromTheHost) 
    { 
     wb.Navigated += handlerFromTheHost; 
    } 

И ничего не сделал.

3. Может быть, я мог бы поделиться классом или переменной, передав его компилируемой сборке?

Итак, вопрос в том, как тот или другой:

  • Как смотреть эффективно для изменения внутри конкретной переменной или свойства внутри скомпилированной программы?

  • Как подключить обратный вызов к хосту?

+0

Что касается q3, вы можете использовать временные файлы и добавить переключатель отладки в CodeDOM компилятор. – leppie

+0

Почему временные файлы и отладочный переключатель? Я хочу либо (1) получить уведомление об изменении переменных в скомпилированном источнике, либо (2) иметь обратный вызов, вызываемый в программе «хост». Прямо сейчас, я ищу, как скомпилированная программа может получить доступ к сборке хоста, поэтому я просто буду следовать за пространством имен для доступа к моим функциям. –

+0

В соответствии с вашим ответом я, кажется, неправильно понял вопрос (+1 для его решения и опубликовать ответ; p) – leppie

ответ

1

Ok. Я получил это: Для того, чтобы получить доступ к хост из скомпилированного источника, единственное, что требуется, чтобы добавить хост-узел в refered сборок в параметрах компилятора:

compilerParams.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); 

Так что нет необходимости в каком-либо специальном обратный вызов или INotifier ,

Вот полный код, который строго отвечает на мой вопрос, и ничего больше:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using Microsoft.CSharp; 
using System.CodeDom.Compiler; 
using System.Reflection; 

namespace MamaProgram 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      string source = 
      @" 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Net; 
using MyMama = MamaProgram;    
namespace Baby 
{ 
    public class Program 
    { 
     public WebBrowser wb = new WebBrowser();   

     public void navigateTo(string url) 
     { 
      wb.Navigated += wb_navigated;    
      wb.Navigate(url);    
     } 

     public void wb_navigated(object sender, WebBrowserNavigatedEventArgs e) 
     {    
      MyMama.Form1.getResult(wb.DocumentText);    
     } 
    } 
} 
      "; 

      Dictionary<string, string> providerOptions = new Dictionary<string, string> 
       { 
        {"CompilerVersion", "v3.5"} 
       }; 

      CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions); 

      CompilerParameters compilerParams = new CompilerParameters 
      { 
       GenerateInMemory = true, 
       GenerateExecutable = false, 
       TreatWarningsAsErrors = false     
      }; 

      compilerParams.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); 
      compilerParams.ReferencedAssemblies.Add("System.Data.dll");    
      compilerParams.ReferencedAssemblies.Add(typeof(System.Linq.Enumerable).Assembly.Location); // Trick to add assembly without knowing their name    
      compilerParams.ReferencedAssemblies.Add(typeof(System.ComponentModel.Component).Assembly.Location); // Trick to add assembly without knowing their name       
      compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll"); 
      CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source); 

      if (results.Errors.Count != 0) 
       throw new Exception("Compilation failed"); 

      object o = results.CompiledAssembly.CreateInstance("Baby.Program"); 
      MethodInfo mi2 = o.GetType().GetMethod("navigateTo"); 
      mi2.Invoke(o, new object[] { "http://www.google.com" });       
     } 

     public static void getResult(string result) 
     { 
      MessageBox.Show(result); 
     }   
    } 
} 
Смежные вопросы