Invoking Methods during Run-Time

Documentation wrote using version 1.2

Invoking methods are pretty easy using rScript. The first thing that needs to happen in order for your application to invoke methods at run-time is the instancing of the ScriptFactory Type. It will instance and provide you with a reference to a Type automatically. You must have a reference to an Assembly that has already been loaded or created. If the compilation of your script was successful, then you will already have a loaded Assembly.
The ScriptFactory does not return an Object that references your script, but rather provides you with a ScriptObject that contains method for invoking methods and accessing properties. It even contains the actual reference to the Type.
The following example extends off the previous example given for compiling scripts. In this example however, we add the ability to invoke the GetTireBramd() method that we created within our script. The example below is using a Console Application project and will compile it as a single file script compilation.

Script.cs
using System;

namespace RuntimeExample.Scripts
{
    public class Wheel
    {
        public Int32 Size = 20;

        public Double Width
        {
            get
            {
                return 8.5;
            }
        }

        public void GetTireBrand()
        {
            System.Windows.Forms.MessageBox.Show("Super Tire Co.");
        }
    }
}


Program.cs
using System;

namespace RuntimeExample
{
    class Program
    {
        static void Main(string[] args)
        {
            rScriptingEngine.CompileEngine _CompileEngine = new rScripting.CompileEngine();
            System.IO.FileInfo file = new System.IO.FileInfo(@"C:\Scripts\Script.cs");

            //The script uses a Windows Forms MessageBox, so we need to reference the correct assembly to prevent compiler errors.
            _CompileEngine.AddAssemblyReference("System.Windows.Forms.dll");

            //Compile the file.
            Boolean isCompiled = _CompileEngine.Compile(file);

            //If it compiled without errro, lets invoke the GetTireBrand() method which will display our messagebox.
            if (isCompiled)
            {
                rScripting.ScriptFactory f = new rScripting.ScriptFactory(_CompileEngine.CompiledAssembly);
                rScripting.ScriptObject obj = f.GetScript("Wheel");
                obj.InvokeMethod("GetTireBrand");
            }
        }
    }
}


As you can see, the ScriptFactory returned a ScriptObject Type that allowed you to invoke the objects method. You also have access to the object itself, via the ScriptObject.Instance Property.
While the previous example is the preferred and safe way to invoke methods, you can do it in another way as well. Thanks to .NET 4.0's new dynamic Type, you can reference the Instance via the dynamic Type and then invoke Methods provided you know the name of the method before hand. If you attempt to invoke a method like this and the method does not exist, then an exception will be generated.

            Boolean isCompiled = _CompileEngine.Compile();
            if (isCompiled)
            {
                rScripting.ScriptFactory f = new rScripting.ScriptFactory(_CompileEngine.CompiledAssembly);
                rScripting.ScriptObject obj = f.GetScript("Wheel");

                dynamic testScript = obj.Instance;
                testScript.GetTireBrand();
            }


One way that this could be used is if you force users to use an interface with their scripts. You can check to make sure the script implements the interface prior invoking it's method, and then dynamically call any of the methods that belong to that interface and rest assured that an exception should not be thrown during run-time.

            Boolean isCompiled = _CompileEngine.Compile();
            if (isCompiled)
            {
                rScripting.ScriptFactory f = new rScripting.ScriptFactory(_CompileEngine.CompiledAssembly);
                rScripting.ScriptObject obj = f.GetScript("Wheel");

                if (obj.Instance.GetType().GetInterface("SomeInterfaceHere") != null)
                {
                    dynamic testScript = obj.Instance;
                    testScript.GetTireBrand();
                }
            }
            else
            {
                Console.WriteLine(_CompileEngine.Errors);
            }


Using that approach will ensure that the method you're calling exists prior to invoking it via a dynamic Type, and help prevent any unexpected exception errors.
You can also load none scripted assemblies into the ScriptFactory and invoke their methods as well.

            System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(@"C:\SomeAssembly.dll");
   
            rScripting.ScriptFactory f = new rScripting.ScriptFactory(assembly);
            rScripting.ScriptObject obj = f.GetScript("SomeType");

            obj.InvokeMethod("SomeMethod");


Although I don't see how you would ever have a reason to do so, but you can even pragmatically load rScript.dll into an Assembly Type, get a reference to the CompileEngine, compile the scripts and invoke script methods during run-time as well.

Last edited Dec 12, 2010 at 2:24 PM by Scionwest, version 7

Comments

No comments yet.