Is it possible to declare IronPython classes as "Export" and thus add them to a MEF catalog that a host C# application can Import?
I cannot really find any concrete examples of this, just speculation.
Here is how I have manually loaded a Python class that implements a .NET interface:
https://github.com/versionone/VersionOne.SDK.Experimental
I would like to be able to put attributes on the python classes similar to how you do it in C#. (Or something equivalent)
Has anyone tried this?
Thanks, Josh
For those interested, I found a project on GitHub that had done this, but was a little bit coupled into the project. With the author's approval I've created a new repo, IronPythonMef, and a NuGet package for it.
There's additional discussion in this thread at GitHub.
Here's an example of how it works:
First, an interface declared in C#:
namespace IronPythonMef.Tests.Example.Operations
{
public interface IOperation
{
object Execute(params object[] args);
string Name { get; }
string Usage { get; }
}
}
An implementation that Exports that interface in C#:
[Export(typeof(IOperation))]
public class Power : IOperation
{
public object Execute(params object[] args)
{
if (args.Length < 2)
{
throw new ArgumentException(Usage, "args");
}
var x = Convert.ToDouble(args[0]);
var y = Convert.ToDouble(args[1]);
return Math.Pow(x, y);
}
public string Name
{
get { return "pow"; }
}
public string Usage
{
get { return "pow n, y -- calculates n to the y power"; }
}
}
And, an implementation of IOperation in IronPython:
@export(IOperation)
class Fibonacci(IOperation):
def Execute(self, n):
n = int(n)
if n == 0:
return 0
elif n == 1:
return 1
else:
return self.Execute(n-1) + self.Execute(n-2)
@property
def Name(self):
return "fib"
@property
def Usage(self):
return "fib n -- calculates the nth Fibonacci number"
And here's a test case of a class that imports these operations from both C# and IronPython and executes them:
[TestFixture]
public class MathWizardTests
{
[Test]
public void runs_script_with_operations_from_both_csharp_and_python()
{
var mathWiz = new MathWizard();
new CompositionHelper().ComposeWithTypesExportedFromPythonAndCSharp(
mathWiz,
"Operations.Python.py",
typeof(IOperation));
const string mathScript =
@"fib 6
fac 6
abs -99
pow 2 4
";
var results = mathWiz.ExecuteScript(mathScript).ToList();
Assert.AreEqual(8, results[0]);
Assert.AreEqual(720, results[1]);
Assert.AreEqual(99f, results[2]);
Assert.AreEqual(16m, results[3]);
}
}