I’m building a C# WebKit Web browser that can be automated with IronPython to aid with Quality Assurance testing. I’ll be creating test plans with IronPython that will run a number of the browser methods, providing the arguments, and evaluating the results.
Most of the documentation for IronPython illustrates how to call IronPython methods with C#, yet I’ve figured out how to set arguments to a method, and how to retrieve a methods return values, but not from the same method. You’ll note in the example below, I’m passing arguments to a method, which in turn is setting a class member variable, and then retrieving that value with another method.
Can anyone suggest a more elegant pattern?
using System; using System.Windows.Forms; using IronPython.Hosting; using Microsoft.Scripting; using Microsoft.Scripting.Hosting; namespace PythonScripting.TestApp { public partial class Form1 : Form { private ScriptEngine m_engine = Python.CreateEngine(); private ScriptScope m_scope = null; //used to call funcs by Python that dont need to return vals delegate void VoidFunc(string val); public Form1() { InitializeComponent(); } private void doSomething() { MessageBox.Show("Something Done", "TestApp Result"); } private string _rslt = ""; private string getSomething() { return _rslt; } private void setSomething(string val) { _rslt = val; } private void Form1_Load(object sender, EventArgs e) { m_scope = m_engine.CreateScope(); Func<string> PyGetFunction = new Func<string>(getSomething); VoidFunc PySetFunction = new VoidFunc(setSomething); m_scope.SetVariable("txt", txtBoxTarget); m_scope.SetVariable("get_something", PyGetFunction); m_scope.SetVariable("set_something", PySetFunction); } private void button1_Click(object sender, EventArgs e) { string code = comboBox1.Text.Trim(); ScriptSource source = m_engine.CreateScriptSourceFromString(code, SourceCodeKind.SingleStatement); try { source.Execute(m_scope); Func<string> result = m_scope.GetVariable<Func<string>>("get_something"); MessageBox.Show("Result: " + result(), "TestApp Result"); } catch (Exception ue) { MessageBox.Show("Unrecognized Python Error\n\n" + ue.GetBaseException(), "Python Script Error"); } } } }
Under normal circumstances, IronPython only has access to public classes and members on .Net types. You should be able to just set your object as a variable in the scope and access any of the public members on that object from your scripts. However the methods you have in your example are
privateso therefore you can’t really access them. If you wish to be able to access them, you need to expose the non-public members somehow so you can manipulate them or use reflection.A pattern you could try would be to add a method that would create a proxy for your object that would have all the methods you would want to expose. Then add that proxy object to your scope then use that proxy to call your methods.
With this, you can execute your scripts accessing your form through the
formvariable or the proxy through theproxyvariable. For good measure, here’s how you could easily access variables and other objects from the scope.