Re: Scripting Engine (somewhat advanced)
From: Joakim Karlsson (jkarlsson_at_NOSPAMjkarlsson.com)
Date: 01/06/05
- Next message: BrianS: "RE: Dynamic Load Assembly"
- Previous message: Kit George: "RE: Getting a problem while developing outlookaddin with c#.net form"
- In reply to: John Puopolo: "Scripting Engine (somewhat advanced)"
- Next in thread: John Puopolo: "Re: Scripting Engine (somewhat advanced)"
- Messages sorted by: [ date ] [ thread ]
Date: Thu, 06 Jan 2005 21:22:05 +0100
You can use the Microsoft.JScript.JScriptCodeProvider to accomplish this.
1. Create a string or temporary file or similar containing a class
declaration and the import statements you need.
2. Paste your script method bodies into the class.
3. Use the ICodeCompiler.CompileAssemblyFromSource to generate an in
memory assembly from the source.
4. Call into the methods of the generated type using reflection.
One caveat: you should load the dynamic assembly into an appdomain of
it's own if you intend to load and unload scripts during execution.
/Joakim
A type for handling this make look something like this:
public class JScriptEngine
{
JScriptCodeProvider codeProvider = new JScriptCodeProvider();
private object scriptInstance;
private ArrayList functions = new ArrayList();
public void AddFunction(string code)
{
functions.Add(code);
}
public void CompileAssembly()
{
// Setup source for script
string source = GenerateSource();
CompilerParameters p = new CompilerParameters(
/*Here you can add references to the host and other assemblies*/);
p.GenerateExecutable = false;
p.IncludeDebugInformation = false;
p.GenerateInMemory = true;
ICodeCompiler c = codeProvider.CreateCompiler();
CompilerResults r = c.CompileAssemblyFromSource(p, source);
if(r.Errors.Count == 0)
{
this.scriptInstance =
r.CompiledAssembly.CreateInstance("Script");
}
else
{
// TODO: Handle compiler errors properly.
}
}
private string GenerateSource()
{
StringBuilder sb = new StringBuilder();
sb.Append(
"import System;\n" +
"import Whatever you need;\n" +
"class Script {\n");
// Add the functions
foreach(string code in functions)
{
sb.Append(code);
}
sb.Append("}\n");
return sb.ToString();
}
public void CallFunction(string name, object[] args)
{
Type type = scriptInstance.GetType();
type.InvokeMember (name,
BindingFlags.InvokeMethod |
BindingFlags.Default,
null, scriptInstance, args );
}
}
John Puopolo wrote:
> All:
>
> I am writing an application (.NET 1.1/C#/VS.NET 2003) that would benefit
> from having a scripting language as part of the program - much like VBScript
> can be used in Excel to automate it.
>
> I would like to use Javascript as the scripting language.
>
> Any idea how I would go about solving this problem? My assumption is that I
> would need to host the scrpting engine and provide calls into and out of the
> engine via some interfaces (COM?). If this is the basic path, I am
> wondering if there is a ".NET" way to do this, or do I need to fall back on
> COM and COM interfaces?
>
> In addition, what if I were to switch from wanting to use Javascript to
> wanting to use C#? I could certainly use the compiler services, etc. to
> load and build an assembly, but how would I expose the host's applicaton
> objects to the script and vice versa?
>
> Many thanks,
> John
>
>
>
>
- Next message: BrianS: "RE: Dynamic Load Assembly"
- Previous message: Kit George: "RE: Getting a problem while developing outlookaddin with c#.net form"
- In reply to: John Puopolo: "Scripting Engine (somewhat advanced)"
- Next in thread: John Puopolo: "Re: Scripting Engine (somewhat advanced)"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|