再次使用我的应用程序的脚本界面。 我想我现在有一个先进的dlr问题。
所以我在.NET和Python之间有一个基本的双向控制流程。
我们走得更远:
我看到我可以使用代码生成来生成代码,如步骤7所示,只需使用步骤8中的成员名称。 但那真的有必要吗?
我没有看到更好的方法a)或b)可能有用,或者可能有一些我没想到的东西。
请不要回答基本的“如何从.NET调用python方法”提示。 这是在步骤1-7中完成的,我这样做没有问题。这确实是一个先进的问题。
namespace DynamicMetaObjectTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Dynamic;
using System.Linq.Expressions;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Hosting.Providers;
class Program
{
internal sealed class CDotNetObject : IDynamicMetaObjectProvider
{
DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression aExp)
{
return new CInvoker(this, aExp);
}
private sealed class CInvoker : DynamicMetaObject
{
internal CInvoker(CDotNetObject aGws, Expression aExp) : base(aExp, BindingRestrictions.Empty, aGws)
{
this.DotNetObject = aGws;
}
private readonly CDotNetObject DotNetObject;
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var aMethodInfo = this.GetType().GetMethod("GetSetResultDelegate");
var aExp = Expression.Call(Expression.Constant(this), aMethodInfo);
var aRestrictions = BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType);
var aMetaObject = new DynamicMetaObject(aExp, aRestrictions);
return aMetaObject;
}
public Action<object> GetSetResultDelegate()
{
return this.DotNetObject.SetResultProvider;
}
}
public void SetResultProvider(object aPythonObject_O2)
{
var aResult = ((dynamic)aPythonObject_O2).GetResult(); // this is for noobs. ;-)
var aMetaObjectProvider = (IDynamicMetaObjectProvider)aPythonObject_O2;
var aMetaObject = aMetaObjectProvider.GetMetaObject(Expression.Constant(aPythonObject_O2));
var aLanguageContext = HostingHelpers.GetLanguageContext(gScriptEngine);
var aMemberNames = aLanguageContext.GetMemberNames(aPythonObject_O2);
var aNonSystemMembers = from aMemberName in aMemberNames where !aMemberName.StartsWith("__") select aMemberName;
foreach (var aMemberName in aNonSystemMembers)
{
Console.WriteLine("Getting function result from Python script: " + aMemberName);
// Now problem:
// P1) How to determine wether its an function or an member variable?
// P2) How to invoke the method respectively get the value of the member variable?
// Your turn ;-)
// some of my failures:
{ // does not work:
//var aVar1Binder = aLanguageContext.CreateGetMemberBinder("GetVar1", false);
//var aVar1Bound = aMetaObject.BindGetMember(aVar1Binder);
//var aCallInfo = new CallInfo(0 , new string[]{});
//var aInvokeBinder = aLanguageContext.CreateCallBinder("GetVar1", false, aCallInfo);
//var aInvokeBound = aMetaObject.BindInvokeMember(aInvokeBinder, new DynamicMetaObject[]{ aVar1Bound});
////var aInvokeExp = Expression.Invoke(Expression.Constant(aInvokeBound), new Expression[] { });
}
{ // does not work
//var aExpandable = (IronPython.Runtime.Binding.IPythonExpandable)aMetaObject;
}
}
}
}
static ScriptEngine gScriptEngine;
static void Main(string[] args)
{
var aScriptRuntime = IronPython.Hosting.Python.CreateRuntime();
// That's the python script from step 1:
var aCode = "class CustomView(object) :" + Environment.NewLine +
"\tdef GetResult(self) :" + Environment.NewLine +
"\t\treturn 42;" + Environment.NewLine + // cuz 42 is the answer to everything ;-)
"DotNetObject.SetResultProvider(CustomView())";
var aEngine = aScriptRuntime.GetEngine("py");
gScriptEngine = aEngine;
var aScope = aEngine.CreateScope();
var aDotNetObject = new CDotNetObject();
aScope.SetVariable("DotNetObject", aDotNetObject);
// That's the invoke to pything from step 3:
aEngine.Execute(aCode, aScope);
}
}
}