I'm generating and executing C# from within a C# program using as described here.
As you can see, one can call "Execute" method of the compiled code via classType.GetMethod("Execute").Invoke(instance, args)
.
The variable args
is an object array of parameters to be passed to the Execute
method. I've been able to pass things relatively easy and without issue using this system.
Now here's the big issue... I need to pass a callback function (eg a Delegate) so that the Execute
method will be able to signal stuff to the main program. I've been trying to pass a typed Delegate that matches the signature, but it failed (wouldn't even run). Next I tried passing a Delegate without specifying the type which also failed (this time it failed at when the call was attempted). I also tried passing it as a normal object and cast it back inside the generated code, but it didn't do anything different.
Since I'm not this much into C#, I think I'm missing something very basic. Also, I don't have a valid test case code...but it shouldn't be too difficult to work with the link I provided above..
See also: http://support.microsoft.com/kb/304655
Edit: This is some sample code:
class CompilerTest {
private object obj;
private MethodInfo mtd;
public void on_log(string type, string message){
MessageBox.Show(type.ToUpper() + ": " + message);
}
public void compile(){
CodeDomProvider c = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.ReferencedAssemblies.Add("system.data.dll");
cp.ReferencedAssemblies.Add("system.windows.forms.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
StringBuilder sb = new StringBuilder("");
sb.AppendLine("using System;");
sb.AppendLine("using System.Data;");
sb.AppendLine("using System.Reflection;");
sb.AppendLine("using System.Windows.Forms;");
sb.AppendLine("public delegate void LoggerInternal(string type, string message);");
sb.AppendLine("public class CSCodeEvalCls{");
sb.AppendLine(" private LoggerInternal log;");
sb.AppendLine(" public void E(object lgr){");
sb.AppendLine(" this.log = (RuleLoggerInternal)lgr;");
sb.AppendLine(" }");
sb.AppendLine(" private void L(string type, string message){");
sb.AppendLine(" this.log(type, message);");
sb.AppendLine(" }");
sb.AppendLine("}");
CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString());
System.Reflection.Assembly a = cr.CompiledAssembly;
this.obj = a.CreateInstance("CSCodeEvalCls");
this.mtd = this.obj.GetType().GetMethod("E");
}
public void execute(){
this.mtd.Invoke(this.obj, new object[]{ this.on_log });
}
}
CompilerTest test = new CompilerTest();
test.compile();
test.execute();