2010-01-25 37 views
3

我繼承了一個小腳本語言,我試圖將它移植到DLR,以便管理起來更容易一些。到目前爲止,它一直相當直接。儘管試圖動態調用變量的成員,但我遇到了一個問題。當前的語言運行在.NET上,並使用解析循環和反射來做到這一點,但我希望擺脫這種情況。這裏是腳本語言的例子:C#3.5 DLR表達式動態問題

string $system1RemoteUri; 
string $dbconnection = $config.GetDBConnection ("somedb"); 
float $minBad = 0.998; 
float $minGood = 0.2; 

$ systen1RemoteURI,$ minBad和$是名古將在腳本中設置,以$ DBConnection的一起變量。但是,$ dbconnection將從一個名爲$ config的變量中獲取它的值。這4個變量需要被調用者使用,所以它們被傳遞給lambda,最初爲null。這裏是產生IL LAMBDA(調試視圖):

.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應該如下所示: 。動態調用GetdbConnection($ config,「somedb」),但我無法弄清楚如何從Expression.Dynamic中實際發出它。

它似乎想要一個CallSiteBinder,我無法正確創建,我不明白參數的順序是什麼Expression.Dynamic,因爲它似乎只想調用「成員」,而不是基地。

我不知道$ config的運行時類型,它只是一些實現GetDBConnection(string)函數的對象。這不是由接口或基類提供的。

任何幫助,將不勝感激。

回答

4

你可以把它變成一個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。

+0

我剛回來回答這個問題,因爲我發現基本上是一樣的。拋出我的是我沒有意識到我需要將基本表達式作爲第一個參數傳遞給Set/Get/Invoke以及之後的其餘參數。 – GrayWizardx 2010-01-26 17:36:52

+0

是否有可以附加到答案的代碼示例? – 2011-01-14 04:38:39