[.net] Easy Scripting in .NET

Started by
72 comments, last by ppp_vcf 16 years, 4 months ago
Thanks for your help!

I changed my code to look like this:

				object Instance = Results[Counter].CompiledAssembly.CreateInstance( ExtractFilename( TempScript.Name ) );				Results[Counter].CompiledAssembly.GetType( ExtractFilename( TempScript.Name ) ).GetMethod( "Init" ).Invoke( Instance, null );


However, now I'm getting the exact same error on the first line. What's happening?
_______________________Afr0Games
Advertisement
Your still not creating an instance of anything.

I don't program in c#, but the concept is basically this.

//declare a variable of type ObjectObject ScriptInstance;//create an instance of a class defined in the "script"//MyClass is the name of an object defined in the script.ScriptInstance = CompiledAssembly.CreateInstance("MyClass");ScriptInstance.GetType.GetMethod("MyMethod").Invoke(null,null);


For this to work your script must define an class. Once you have an instance of that class, you can get its methods and invoke them.

class MyClass{    public MyMethod()    {        //more code here.    } }


You don't need to find a path to the compiled assembly or anything like that since its already loaded into memmory, when it was compiled. This is because you told the compiler to do that. Params.GenerateInMemory = true;

From what I can tell, yes, I am creating an instance. If you're wondering why I'm using the ExtractFilename() method in combination with the CreateInstance() method, it's because all my scripts have classes that are named after the files they reside in, to make the loading easier. I'm still confused here. :( Any more input, please?
_______________________Afr0Games
In a recent project I've been using JSCRIPT similar to how you use C#, to parse and evaluate expressions, basically ResultString = ParseExpression("5*25");
but it's fairly slow. Will I gain any speed by switching to the C# Compiler?

Also, seems to me since it's only an expression, is there anyway to compile the app into bytecode or whatever form it takes to run on the clr, and just change the constant values of the expression?(As there are no variables used, litterally either constant strings or numbers)

Surely that would be a huge speed up, but I have no idea if this relates to it or am I barking up the wrong tree?

Afr0m@n, I really need to pay attention.

object Instance = Results[Counter].CompiledAssembly.CreateInstance( ExtractFilename( TempScript.Name ) );Instance.GetType.GetMethod( "Init" ).Invoke( Instance, null );


AP,
Quote:Original post by Anonymous Poster
In a recent project I've been using JSCRIPT similar to how you use C#, to parse and evaluate expressions, basically ResultString = ParseExpression("5*25");
but it's fairly slow. Will I gain any speed by switching to the C# Compiler?


I don't know without seeing your code, but the technique described in this thread really is not meant for casual evaluations. Its really meant for the situation where you have a lot of methods defined that you want to call repeatedly in your app. The problem is that compiling an assembly, and creating instances of classes from it has a lot of overhead. Its not bad if you app does this once at start up or infrequently when loading a level, but used frequently to evaluate expressions, then you will have problems.
Quote:Original post by VizOne
The managed DX scripting example uses exactly this technique.


Here a code snippet how to setup a "sandbox"-AppDomain
*** Source Snippet Removed ***

Regards
Andre


two problems! i'm trying to use this in asp.net and i get "Could not load file or assembly 'EvalTest' or one of its dependencies. The system cannot find the file specified. " in CreateInSeparateDomain() -> return dom.CreateInstanceAndUnwrap( typeof( ScriptRunner ).Assembly.GetName().Name, typeof( ScriptRunner ).FullName ) as ScriptRunner;

it works fine in ConsoleApplication, without asp.net.

when i try to use CreateInstanceFromAndUnwrap("EvalTest.dll"...) instead, it doesn't show this error, but probably loads another assembly clone so i then get strange errors with remoting (The argument type 'System.MarshalByRefObject' cannot be converted into parameter type 'EvalTest.WikiGate'.).

and it seems that permissions to work must be set exactly in the method where the script is executed! not in the constructor. Or else the script can delete all files without restrictions.
AppDomain.CurrentDomain.SetAppDomainPolicy(level);

[Edited by - exe55 on April 19, 2007 11:44:22 PM]
Quote:Original post by Anonymous Poster
In a recent project I've been using JSCRIPT similar to how you use C#, to parse and evaluate expressions, basically ResultString = ParseExpression("5*25");
but it's fairly slow. Will I gain any speed by switching to the C# Compiler?

Also, seems to me since it's only an expression, is there anyway to compile the app into bytecode or whatever form it takes to run on the clr, and just change the constant values of the expression?(As there are no variables used, litterally either constant strings or numbers)

Surely that would be a huge speed up, but I have no idea if this relates to it or am I barking up the wrong tree?

The ParseExpression function is an interpreter, it does not compile to bytecode before running. Incidentally, the JScript compiler is also available, in a similar manner to what is described here for C#. I personally prefer using JScript as a scripting language, as it's a much simpler syntax for users to get used to.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

I was looking at CS-Script (http://www.members.optusnet.com.au/~olegshilo/). Anyone know anything about it and if it's better than using Microsoft.CSharp namespace?
Good information! Now I have a couple questions. Can I access public fields created inside of the C# script with my C# application compiling the script?

I am wanting to use the C# script as a scripting language for my MUD engine, each NPC's will have various scripts associated with them as well as various objects that can execute scripts when used. I am wanting to store various values (such as object health or NPC's updated location) within the script while it's executing and once the execution is finished, return those values back to the game engine library so that they can be stored with the NPC loaded within my game engine. Sorry if this doesn't make much sense. Can this be done? Also can my scripts access my C# Application variables that are currently in memory? My engine always has a projectPath variable defined and a value assigned to it. I need to access it from my scripts, do I just pass arguments to the script or can I just access the value directly from the script?

Thanks for any comments!
Scionwest
Quote:Original post by Scionwest
Good information! Now I have a couple questions. Can I access public fields created inside of the C# script with my C# application compiling the script?

I am wanting to use the C# script as a scripting language for my MUD engine, each NPC's will have various scripts associated with them as well as various objects that can execute scripts when used. I am wanting to store various values (such as object health or NPC's updated location) within the script while it's executing and once the execution is finished, return those values back to the game engine library so that they can be stored with the NPC loaded within my game engine. Sorry if this doesn't make much sense. Can this be done? Also can my scripts access my C# Application variables that are currently in memory? My engine always has a projectPath variable defined and a value assigned to it. I need to access it from my scripts, do I just pass arguments to the script or can I just access the value directly from the script?

Thanks for any comments!
Scionwest


I have not tried this scripting stuff yet, but I would imagine if you load the script into memory, you could do a simple String.Replace to place your own variable values into the script. Eg. Say you load the following script into memory..

string path=[ProjectPath];System.Windows.Forms.MessageBox.Show(path);


Once you load the script into memory, your could just do a script.Replace("[ProjectPath]", projectPath);

You could have a bunch of "built in" variables that users can use that you go through and String.Replace before executing the script. That's how I would do it, but if anyone with more experience using scripting has a better way please post it here.

EDIT: I missed a post where it explains passing variables through arguments

Quote:Way back in the origional post there was the line:
results.CompiledAssembly.GetType( "Script").GetMethod( "Main" ).Invoke( null, null );

The Second parameter to Invoke is either Null for a method that has no parameters, or an array of objects for a method that requires parameters. The size of the array should match the number of parameters in the method that is about to be called.


[Edited by - Headkaze on May 5, 2007 10:02:14 AM]

This topic is closed to new replies.

Advertisement