I have one question, I have such code
this._engine = Python.CreateEngine();
ScriptSource source = this._engine.CreateScriptSourceFromString(script.SourceCode);
ScriptScope scope = this._engine.CreateScope();
ObjectOperations operations = this._engine.Operations;
source.Execute(scope);
And I am trying to execute IronPython code from tutorial:
from System.Collections import BitArray
ba = BitArray(5)
ba.Set(0, True) # call the Set method
print ba[0]
So it executes correctly, but I can't understand if i have print ba[0] why it doesn't output this value to the console? By the way, could you advice some good articles about using IronPython for applications scripting?
And another question is if I have some Python class and I do not know the name of this class, because the client can define it manually, is it possible to create an instance of this class? For example
class SomeClass(object):
def some(self, a, b):
return <something>
Now I'm trying to use this code
dynamic SomeClass = scope.GetVariable("SomeClass");
dynamic something = SomeClass();
something.some(x,y);
Should I iterate through ScriptScope.GetItems() collection and search for PythonType objects?
I think you just need to call:
this._engine.Runtime.IO.RedirectToConsole();
Otherwise have a look here for a similar question about redirecting.
About python class instantiation in C#, your code seems to be ok, as shown in this question (look at the 3rd answer)
EDIT:
Sorry I didn't read your question with enough attention...
Anyway, to look for available classes in Python, just do as you said,
i.e. something like:
var availDynClasses = items.Where(x => x.Value is IronPython.Runtime.Types.PythonType);
Related
For a project, I require that my users are able to provide a simple function as a string, and I want to be able to evaluate it from my program.
Let's say the function signature is always int f(int a, int b)
I want to make it so that my users can provide implementations of f written in a basic language.
For instance:
return a*b;
if(a ==1) return b else return 3
And in my program, I want to be able to parse the user input function to make it a real callable function from my C# code. I only require basic features like basic math stuff and conditionals (not even loops).
Is there a basic "language" that exists that would allow me to interpret such functions defined as input and transform them in callable code?
For instance I think that using Lua for this overkill?
Ideally I want something open-source, with minimal codebase and that is widely known to be of good quality. Does such a thing exist? Ideally it should also have implementations in several languages, like C# and Java.
I know the temptation to write my own parser is high but I feel like there must be an out-of-the-box solution for my problem
If you only need math functions you can just have take in a string an eval it in a data table then return the results.
using System.Data;
//string mathExp = "3 * (2+4)"
public string ShiestyEval(string mathExp)
{
DataTable dt = new DataTable();
var v = dt.Compute(mathExp,"");
return v;
}
To get it to be callable from your application, you need to provide an interface in which they can eval there methods, or if you wanna do some shady hack and generate an assembly though Il, and load it you can, it's a little vague on how you want to use it
you can also checkout JSharp
I don't think there is a simple way to do it. But there are some solutions that are easy to use. I really like Irony had a lot of fun with it. But it's a bit abandoned. You can use ANTLR but this one is not simple. You might be able to use Roslyn Api to do what you want it all depends. I am not sure how good of a sandbox do you need but you can use C# scripts
This will allow you to do something like this
ScriptState state = CSharpScript.Run("int Times(int x) { return x * x; }");
var fn = state.CreateDelegate>("Times");
var value = fn(5);
Console.Write(value);
I’m trying to pass a COM object from C# code to Perl.
At the moment I’m wrapping my Perl code with PerlNET (PDK 9.4; ActiveState) and I have defined a simple subroutine (+ required pod declaration) in Perl to pass objects from C# to the wrapped Perl module.
It seems that the objects I pass are not recognized correctly as COM objects.
An example:
In C# (.NET 4.0), the ScriptControl is used to load a simple class from a file written in VBScript.
var host = new ScriptControl();
host.Language = "VBScript";
var text = File.ReadAllText("TestScript.vbs");
host.AddCode(text);
dynamic obj = host.Run("GetTestClass");
What I get (obj) is of type System.__ComObject. When I pass it to my Perl/PerlNET assembly and try to call method Xyz() in Perl I get the following (runtime) exception:
Can't locate public method Xyz() for System.__ComObject
If, however, I do more or less the same thing in Perl, it works. (In the following case, passing only the contents of my .vbs file as parameter.)
I can even use the script control :
sub UseScriptControl {
my ($self, $text) = #_;
my $script = Win32::OLE->new('ScriptControl');
$script->{Language} = 'VBScript';
$script->AddCode($text);
my $obj = $script->Run('GetTestClass');
$obj->Xyz();
}
Now, calling Xyz() on obj works fine (using Win32::OLE).
In both cases I use:
use strict;
use Win32;
use Win32::OLE::Variant;
Another approach:
I can invoke methods by using InvokeMember of class System.Type if I specify exactly which overload I want to use and which types I’m passing:
use PerlNET qw(typeof);
typeof($obj)->InvokeMember("Xyz",
PerlNET::enum("System.Reflection.BindingFlags.InvokeMethod"),
PerlNET::null("System.Reflection.Binder"),
$obj,
"System.Object[]"->new());
Using this approach would mean rewriting the whole wrapped Perl module. And using this syntax..
Now I am wondering if I am losing both the advantages of the dynamic keyword in .NET 4.0 and the dynamic characteristics of Perl (with Win32::OLE) by using PerlNET with COM objects.
It seems like my preferred solution boils down to some way of mimicking the behaviour of the dynamic keyword in C#/.NET 4.0.
Or, better, finding some way of converting the passed COM object to something that will be recognized as compatible with Win32::OLE. Maybe extract some information of the __ComObject for it to be identified correctly as COM object.
I have to add that I posted to the PDK discussion site too (but didn’t get any response yet): http://community.activestate.com/node/18247
I also posted it to PerlMonks - as I'm not quite sure if this is more a Perl or C#/.NET question:
http://www.perlmonks.org/?node_id=1146244
I would greatly appreciate any help - or advise on where to look further.
I would like to generate syntax nodes with the Roslyn API without having a pre-existing syntax node. That is, I cannot simply use the WithXYZ() methods on an existing object to modify it because there is no existing object.
For example, I would like to generate an InvocationExpressionSyntax object. Assuming a constructor was available, I could do something like
var invoke = new InvocationExpressionSyntax(expression, arguments);
But the constructor for InvocationExpressionSyntax seems to not be public.
http://www.philjhale.com/2012/10/getting-started-with-roslyn.html
this blog suggests that I can use an API such as
Syntax.InvocationExpression()
but I don't see what Syntax refers to, and I don't see anything that resembles it in the Roslyn API.
I did find Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory that lets me do
var invoke = SyntaxFactory.InvocationExpression().WithExpression(expression);
And this works well enough for me. There is also Microsoft.CodeAnalysis.CSharp.SyntaxFactory for anyone wondering.
Is SyntaxFactory the proper way to create new syntax nodes?
The way I found SyntaxFactory.InvocationExpression was by looking at the PublicAPI.txt file in the roslyn source code (https://github.com/dotnet/roslyn) under the src/Compilers/VisualBasic/Portable directory. Otherwise, I don't see where SyntaxFactory is documented.
As the other answer stated, the SyntaxFactory is the correct class to use. As you have found there are two syntax factories available, Microsoft.CodeAnalysis.CSharp.SyntaxFactory and Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory, depending on which language you are using.
Usually the calls into the SyntaxFactory are chained together, so you end up with many calls to the SytnaxFactory methods to generate even simple lines of code. For example, the code Console.WriteLine("A"); would be represented by the following calls to the Syntax Factory:
var console = SyntaxFactory.IdentifierName("Console");
var writeline = SyntaxFactory.IdentifierName("WriteLine");
var memberaccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, console, writeline);
var argument = SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("A")));
var argumentList = SyntaxFactory.SeparatedList(new[] { argument });
var writeLineCall =
SyntaxFactory.ExpressionStatement(
SyntaxFactory.InvocationExpression(memberaccess,
SyntaxFactory.ArgumentList(argumentList)));
If you are unsure of how to generate nodes for some specific code, Kirill Osenkov created the Roslyn Quoter project on GitHub, which you can use to generate the SyntaxFactory code for you.
I recently did a blog post on this topic if you would like to read further.
Yes, the SyntaxFactory type is the way to create syntax nodes from scratch.
I'm working on a WPF application that validates C# code from files.
I was able to get the file and, for a different need, instantiate its type.
Now what I need is validate that code against some criteria I set.
What do I mean?
Let's say I have a file "Test.cs" and this file has the following code:
using xpto;
using abcd;
public class Test
{
public static void Testing()
{
Iqueryable<XYZ> var1 = ctx.Where(c => c.IdSomething == number);
var1 = var1.Where(v => v.Count(x => x.ValZ) > 0);
}
}
In my app I would instantiate this file (already being done) and then validate it against some rules. For instance, in this line:
var1 = var1.Where(v => v.Count(x => x.ValZ) > 0);
I want to tell that the file is using Count(...) > 0 instead of Any(). I know that can be done by text reading the file, but I wanted to know if that's possible using reflection, or any other way that would not require such hard coding.
This is what I do to instantiate the file (this is a working example):
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile.FullName);
Type instanceType = cr.CompiledAssembly.GetExportedTypes()
.FirstOrDefault(e => e.Name.Equals(className));
If this is not clear, please let me know so I can try to elaborate.
Well, even if question tends to be too general, you can do it with Microsoft Roslyn. The compiler as a service which you can use
to get AST from the code provided and recieve all nececssary information you need.
As this is big stuff, it's hardly can be presented here with some short and self explanatory answer. It's easier to have a look on concrete example for "how to run stuff", for example here:
Roslyn CTP: Three Introductory Projects
I'm sure this is an easy fix and I just can't find it, but here goes:
I have a C# class (let's call it Test) in an assembly (let's say SOTest.dll).
Here is something along the lines of what I'm doing:
private List<string> items;
public List<string> list_items()
{
return this.items;
}
public void set_items(List<string> new_items)
{
this.items = new_items;
}
In the IronRuby interpreter I run:
>>> require "SOTest.dll"
true
>>> include TestNamespace
Object
>>> myClass = Test.new
TestNamespace.Test
>>> myClass.list_items()
['Apples', 'Oranges', 'Pears']
>>> myClass.set_items ['Peaches', 'Plums']
TypeError: can't convert Array into System::Collections::Generic::List(string)
I get a similar error whether I make the argument a 'List< string >', 'List< object >' or 'string[ ]'.
What is the proper syntax? I can't find a documented mapping of types anywhere (because it's likely too complicated to define in certain scenarios given what Ruby can do).
EDIT:
It doesn't look like what I was trying to do is possible. I'll have to include the IronRuby assembly in the .NET project so the input can be an IronRuby type to keep the scripting interface cleaner.
If anybody comes up with a way to make it work how I originally wanted, I'll change the accepted answer.
You will have to construct the list a bit differently:
ls = System::Collections::Generic::List.of(String).new
ls.add("Peaches")
ls.add "Pulms"
Never used it, but I'm guessing something like:
myClass.set_items(System::Collections::Generic::List(string).new ['Peaches', 'Plums'])
That is, construct a List<string> from the array. I'm doubtful of the System::Collections::Generic::List(string) part, but judging from the error message, that's how to give the fully qualified name of a List<string> in IronRuby.