C # 3.5 DLR Expression.Dynamic Question

I have inherited a small scripting language and I am trying to port it to DLR so that it is a little easier to manage. Until now, he has been pretty direct. I ran into a problem, although I am trying to dynamically call members of a variable. The current language runs on .NET and uses a parsing and reflection cycle to do this, but I was hoping to get away from it. Here is an example 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 the variable passed in the called $ config. 4 variables must be available to the caller, so they are passed to 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"); } 

I am trying to figure out how to use Expression.Dynamic to emit $ config.GetDBConnection ("somedb"). From a look at the examples in Sympl libraries, I believe that the emitted IL should look like this: .Dynamic Call GetdbConnection ($ config, "somedb"), but I can’t figure out how to actually fix this from Expression.Dynamic.

It seems you need a CallSiteBinder that I cannot create correctly, and I don’t understand what order of parameters the Expression.Dynamic expression has, since it seems to want the called member to be called, not the base.

I don’t know the type of environment $ config, it’s just some kind of object that implements the GetDBConnection (string) function. This is not provided by an interface or base class.

Any help would be appreciated.

+3
source share
1 answer

You can either turn this into an InvokeMemberBinder, or include "$ config.GetDBConnection" in GetMember, and then execute Invoke as a result of passing $ someDb as an argument.

To implement GetMemberBinder and InvokeMemberBinder, you can use the External DLR class DefaultBinder. In the latest IronPython / IronRuby source code, you can simply create a new instance of DefaultBinder from the air. Then in your FallbackGetMember / FallbackInvoke you can call defaultBinder.GetMember (...) and defaultBinder.Call (which should be renamed Invoke). This applies to most .NET types for you. All objects that implement IDynamicMetaObjectProvider will also work. For other dynamic operations, you can use other methods for the default binder. And if you want to start customizing your overload and binding rules, you have many buttons that you can rotate.

Unfortunately, by default, there is no InvokeMemberBinder implementation for the binder right now, so you will probably be better off working with GetMember / Invoke.

+4
source

Source: https://habr.com/ru/post/1335327/


All Articles