C# 3.5 DLR 表达式.动态问题
我继承了一种小型脚本语言,并尝试将其移植到 DLR,以便更容易管理。到目前为止,一切都相当简单。我在尝试动态调用变量的成员时遇到了问题。当前的语言在 .NET 上运行,并使用解析循环和反射来执行此操作,但我希望摆脱这种情况。以下是脚本语言的示例:
string $system1RemoteUri;
string $dbconnection = $config.GetDBConnection ("somedb");
float $minBad = 0.998;
float $minGood = 0.2;
$systen1RemoteURI、$minBad 和 $minGood 是将在脚本中与 $dbconnection 一起设置的变量。但是 $dbconnection 将从名为 $config 的变量中获取其值。这 4 个变量需要可供调用者使用,因此它们被传递到 lambda 中,最初为 null。这是生成的 Lambda IL(调试视图):
.Lambda #Lambda1<Delegate6$1>(
System.String& $$system1RemoteUri,
System.String& $$dbconnection,
System.Double& $$minBad,
System.Double& $$minGood
System.Object $$config) {
.Block() {
$$minBad = 0.998D;
$$minGood = 0.2D
}
//Some assignment similar to...
//.Dynamic Call GetDBConnection($config, "somedb");
}
我试图弄清楚如何使用 Expression.Dynamic 发出 $config.GetDBConnection("somedb")。通过查看 Sympl 库中的示例,我相信发出的 IL 应该如下所示: .Dynamic 调用 GetdbConnection($config, "somedb") 但我无法弄清楚如何从 Expression.Dynamic 实际发出它。
它似乎想要一个我无法正确创建的 CallSiteBinder,并且我不明白 Expression.Dynamic 的参数顺序是什么,因为它似乎只想要调用“成员”,而不是基础。
我不知道 $config 的运行时类型,它只是一些实现名为 GetDBConnection(string) 的函数的对象。这不是由接口或基类提供的。
任何帮助将不胜感激。
I have inherited a small scripting language and I am attempting to port it to the DLR so that it is a little easier to manage. So far it has been fairly straight forward. I have run into a problem though attempting to dynamically call members of a variable. The current language runs on .NET and uses a parsing loop and reflection to do this, but I was hoping to get away from that. Here is an example of the script language:
string $system1RemoteUri;
string $dbconnection = $config.GetDBConnection ("somedb");
float $minBad = 0.998;
float $minGood = 0.2;
$systen1RemoteURI, $minBad, and $minGood are variables that will be set in the script, along with $dbconnection. However $dbconnection will get its value from a variable passed in called $config. The 4 variables need to be available to the caller, so they are passed into the lambda, initially as null. Here is the generated Lambda IL (debug view):
.Lambda #Lambda1<Delegate6$1>(
System.String& $system1RemoteUri,
System.String& $dbconnection,
System.Double& $minBad,
System.Double& $minGood
System.Object $config) {
.Block() {
$minBad = 0.998D;
$minGood = 0.2D
}
//Some assignment similar to...
//.Dynamic Call GetDBConnection($config, "somedb");
}
What I am trying to figure out is how to use Expression.Dynamic to emit the $config.GetDBConnection("somedb"). From looking at examples in the Sympl libraries I believe the emitted IL should look like:
.Dynamic Call GetdbConnection($config, "somedb") but I cant figure out how to actually emit that from Expression.Dynamic.
It seems to want a CallSiteBinder which I cannot create correctly, and I do not understand what the order of parameters is to Expression.Dynamic, as it seems to only want the "member" being invoked, and not the base.
I do not know the runtime type of $config it is just some object which implements a function called GetDBConnection(string). This is not provided by an interface or base class.
Any help would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以将其转换为 InvokeMemberBinder 或将“$config.GetDBConnection”转换为 GetMember,然后对传递 $someDb 作为参数的结果执行 Invoke。
要实现 GetMemberBinder 和 InvokeMemberBinder,您可以使用 DLR 外层 DefaultBinder 类。在最新的 IronPython/IronRuby 源代码中,您可以凭空创建一个新的 DefaultBinder 实例。然后在 FallbackGetMember / FallbackInvoke 中,您可以调用 defaultBinder.GetMember(...) 和 defaultBinder.Call (应重命名为 Invoke)。这将为您处理大多数 .NET 类型。此外,所有实现 IDynamicMetaObjectProvider 的对象也可以使用它。对于其他动态操作,您可以使用默认活页夹上的其他方法。如果您想开始自定义重载解析和绑定规则,它有很多可以转动的旋钮。
不幸的是,默认绑定器现在没有 InvokeMemberBinder 实现,因此您最好使用 GetMember/Invoke。
You can either turn this into an InvokeMemberBinder or turn "$config.GetDBConnection" into a GetMember and then do an Invoke on the result of that passing $someDb as the argument.
To implement your GetMemberBinder and InvokeMemberBinder you can use the DLR outer-layer DefaultBinder class. In the latest IronPython/IronRuby source code you can just create a new DefaultBinder instance out of thin air. Then in your FallbackGetMember / FallbackInvoke you can call defaultBinder.GetMember(...) and defaultBinder.Call (which should be renamed Invoke). That'll deal with most .NET types for you. Also all objects which implement IDynamicMetaObjectProvider will work with it as well. For other dynamic operations you can use the other methods on the default binder. And if you want to start customizing your overload resolution and binding rules it has lots of knobs you can turn.
Unfortunately the default binder doesn't have an InvokeMemberBinder implementation right now so you're probably better off w/ GetMember/Invoke.