2012-04-17 74 views
1

我有一個情況,我有一個可調用的「動態」類型的對象。我試圖實現一個函數,它將在運行時用一組參數動態調用對象。這是很容易調用它,如果我知道的參數的數量在編譯時:是否可以在C#中調用動態對象?

Object StaticInvoke(dynamic func, Object[] args) { 
    // arguments are explicitly unwrapped and bound to the invokation 
    // requiring that we know the number at compile time 
    return func(args[0], args[1], ...); 
} 

但是,這並不能達到我想要的東西,因爲args數組是可變的長度。我無法找出一種方法來支持任意數量的參數。最近我想出的是這樣的:

static Object Invoke(dynamic func, Object[] args) 
{ 

    // not sure what to put here 
    switch(args.Length) 
    { 
     case 0: 
      return func(); 
     case 1: 
      return func(args[0]); 
     case 2: 
      return func(args[0], args[1]); 
     ... 
     default: 
      throw new NotSupportedException(); 
    } 
} 

這將限制我可能傳遞的參數的數量。我想我可以忍受這個限制,但感覺就像我想要做的事情應該是可能的。

我基本上試圖在C#中實現JavaScript「應用」功能。有沒有更簡單的方法來完成我想要做的事情?我覺得我失去了一些明顯的東西。

+1

爲什麼你的代碼的用戶會直接調用'Invoke'而不是直接調用'func(...)'? – 2012-04-17 17:57:25

+0

我懷疑有一種內置的方式來做你正在嘗試使用反射來做的事情,但我不是那方面的專家。相反,我會提到,如果你想在C#中使用可變數量的參數,你應該看看'params'關鍵字。我的免責聲明是,我不認爲你實際上需要'params',你想調用一個使用反射的方法。 – 2012-04-17 18:16:08

+0

@ M.Babcock:我試圖創建的「invoke」是實現一個接口方法,以便我們可以像使用舊腳本引擎中的「傳統」調用一樣使用新的動態調用。 – MarkPflug 2012-04-17 18:35:24

回答

1

的開源Apache許可證ImpromptuInterface(上的NuGet)有一個靜態方法Impromptu.Invoke做這個。您可以查看實現,同時處理任意數量的參數,但它也可以執行您可能不需要的工作,例如提供一種機制來動態描述命名參數並調用它們。

根據您的使用情況,您的交換機案例想法可能實際上是一種方法,因爲它應該既簡單又快速。

對於您的開關盒,N是您支持的最大參數數量,C#編譯器將創建N + 1個電話號碼,它只是靜態地知道它們的位置。即興將調用dlr apis,就像編譯器一樣,但它會是storing the callsite in a hashtable,這會增加查找時間(儘管如此)。

dlr api還需要一個委託,它的簽名與您所調用的數字或參數相匹配,編譯器會確保您靜態地有N + 1個委託,而Impromptu將使用17個內置的Func < >在開關盒中,然後start emiting new delegates as needed,這是一次性生產成本,然後爲隨後的調用添加更多散列表查找。

+0

即興的東西看起來有點矯枉過正,我需要的東西。我想這個開關就夠好了。謝謝(你的)信息! – MarkPflug 2012-04-21 00:18:14

0

編輯:這不是一個答案 - 保持它在這裏,讓別人知道它不可能是@Mark尋找。

對於常規的對象你會使用MethodBase.InvokeMethod

MethodInfo magicMethod = magicType.GetMethod("ItsMagic"); 
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100}); 
+0

否;他正在嘗試使用'IDynamicMetaObjectProvider'。 – SLaks 2012-04-17 18:05:00

相關問題