2013-04-18 147 views
0

我想知道是否可以通過字符串調用動態c#對象上的函數。我想要做這樣的事情:我可以使用字符串方法名稱調用c#動態方法嗎?

string lMethodName = "MethodName"; 
dynamic lDynamicObject = GetDynamicObject(); 
lDynamicObject.Invoke(lMethodName, lParameters); 

任何想法或解決方案將不勝感激。

也許像Servy說的那樣,有一種更好的方法可以通過不同的設計來實現我們想要的。我們正在使用SignalR並擁有一個儀表板網絡應用程序。我們希望儀表板內的每個小部件都能夠將數據推送到它。爲了實現這一點,我們將使用剃鬚刀代碼將widget ID注入到每個單獨的小部件SignalR clientside代理中。每個部件將具有以下內容:

hub.client.updateWidget123456 = aUpdateFunction; 

其中123456是小部件的ID。在服務器端SignalR基地代碼,我們可以回調到客戶方javascript函數:

int lWidgetId = 123456; 
dynamic lDynamic = Clients.All; 
lDynamic.Invoke("updateWidget" + lWidgetId, lParameters); 

還有其他的方法我能想到的實現這一點沒有創建JavaScript代理方法。我認爲這很好,因爲服務器與每個單獨的小部件有直接的通信線路。哪些可以從多個儀表板/瀏覽器訪問,但它們都將通過上面的單個調用進行更新。

我們可以通過調用javascript客戶端代碼中的其他對象來實現此目的,這些對象知道所有的小部件以及如何將信息引導給它們。我覺得這跟SignalR的hub結構相反,就像我們通過這樣做重新發明了輪子。

有沒有人有更好的設計方法的任何想法?感謝您的幫助和感謝您的評論Servy引發這個討論。

另外,這個問題不是重複的。另一個問題不是像保羅這樣的動態對象在下面進行評論。

+0

dup:http://stackoverflow.com/questions/540066/calling-a-function-from-a-string-in-c-sharp – dotNET

+1

不,這個問題是針對動態類型的,另一個問題是針對反射一般來說。 – Paul

+1

你幾乎肯定不想這樣做。你應該*強烈*考慮重新設計你的代碼,這樣你就不需要這樣做。 – Servy

回答

1

如果您知道它是一個普通的C#對象(即沒有特殊的運行時綁定器),則只能使用反射來調用dynamic上的方法。

考慮下面的類實現可以動態使用特性包:

public class PropertyBag : DynamicObject 
{ 
    private Dictionary<string, object> _propertyBag = new Dictionary<string, object>(); 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     return _propertyBag.TryGetValue(binder.Name, out result); 
    } 

    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     _propertyBag[binder.Name] = value; 
     return true; 
    } 

    public override IEnumerable<string> GetDynamicMemberNames() 
    { 
     return base.GetDynamicMemberNames(); 
    } 
} 

這是完全有效的做到以下幾點:

dynamic propertyBag = new PropertyBag(); 

propertyBag.Name = "stackoverflow"; 
propertyBag.Value = 42; 

然而,如果你嘗試獲得PropertyInfo對於任何這些動態屬性,它將失敗,因爲PropertyBag類沒有實現它們:

public static void SetProperty(dynamic propertyBag, string propertyName, object value) 
{ 
    PropertyInfo property = propertyBag.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance); 
    if (property == null) 
    { 
     throw new NotImplementedException(); 
    } 

    MethodInfo setProperty = property.GetSetMethod(); 
    setProperty.Invoke(propertyBag, new object[] { value }); 
} 

這將拋出一個異常:

dynamic propertyBag = new PropertyBag(); 

propertyBag.Name = "stackoverflow;  // works as expected 
SetProperty(propertyBag, "Value", 42); // throws a NotImplementedException 

我在這個例子中使用屬性,因爲它們更容易實現,但顯然同樣適用於方法了。原因是dynamic在運行時動態評估,但反射只能反映靜態實現。 (應GetProperties回報的PropertyBag類?什麼樣的屬性)

如果使用dynamic與普通C#對象如預期反思工作,但你不能依賴,如果你不知道你是adressing什麼類型的運行時綁定的以及它是如何在內部實施的。

1

通過反思,我認爲你可以做這樣的事情(如果是私密 - >非公開)

MethodInfo dynMethod = this.GetType().GetMethod("MethodName" + itemType, BindingFlags.NonPublic | BindingFlags.Instance); 
dynMethod.Invoke(this, new object[] { methodParams }); 

只需使用GetMethod重載版本接受的BindingFlags:

0

是的,它是可能的。你想要做的就是所謂的「反射」,並且可以在大多數高級語言中使用。

以下是reflection in C的示例。它實際上是非常強大的,可以讓你讓你的代碼「意識到自己」達到一定程度

1

簡短的回答,是的,你可以做這樣的事情:

 class MyClass { public void Action() { Console.WriteLine("Do action"); } } 
     // ... 
     dynamic instance = new MyClass(); 
     instance.GetType().GetMethod("Action").Invoke(instance, null); 

然而,在這種情況下,實例是動態類型的事實完全沒有。您可以使用object類型,它的工作方式也是一樣。鏈中的第一個方法,GetType()返回typeof(MyClass),然後從那裏開始就是普通的舊時尚反射。

使用動態關鍵字,你可以做到這一點,這是更有趣的,雖然略少靈活的運行時:

 dynamic instance = new MyClass(); 
     instance.Action(); 

這將在運行時使用反射查找的動作。在這個例子中dynamic的作用與var不同,因爲這裏設置了MyClass,但是你可以使用第二行來執行任何名爲action的方法,只要這個實例有一個名字的方法。

相關問題