8

我正在尋找一種動態添加成員到動態對象的方式。 OK,我想是需要澄清一下......動態添加成員到動態對象

當你做到這一點:

dynamic foo = new ExpandoObject(); 
foo.Bar = 42; 

Bar屬性將在運行時動態添加。但是代碼仍然將「靜態」引用到Bar(名稱「Bar」是硬編碼的)......如果我想在運行時添加一個屬性而不知道它在編譯時的名稱怎麼辦?

我知道如何用自定義動態對象(其實我blogged about it幾個月前)做到這一點,利用DynamicObject類的方法,但我怎麼能與任何動態對象做呢?

我大概可以使用IDynamicMetaObjectProvider接口,但我不明白如何使用它。例如,我應該將什麼論點傳遞給GetMetaObject方法? (它預計Expression

順便說一下,你如何執行對動態對象的反射? 「經常」反思和TypeDescriptor不顯示動態成員...

任何有識之士將不勝感激!

+0

在C#6.0中,*可以是*你可以像'foo。$ Bar = 42;'一樣寫* :)不知道是否允許動態... – nawfal 2014-07-21 12:25:25

+0

@nawfal,實際上,該功能已被刪除.. 。但無論如何,'foo。$ Bar'只是'foo [「Bar」]的簡寫'' – 2014-07-21 12:26:33

+0

Thomas,不知道被丟棄的功能(我很高興),但是哦,是的,一會兒我忽略了你q的真正需求。 – nawfal 2014-07-21 12:28:46

回答

9

你想要的是類似於Python的getattr/setattr函數。在C#或VB.NET中沒有內置的等效方法。 DLR的外層(在Microsoft.Scripting.dll中帶有IronPython和IronRuby)包含一組託管API,其中包含具有GetMember/SetMember方法的ObjectOperations API。你可以使用這些,但你需要DLR和基於DLR的語言的額外依賴。

也許最簡單的方法是創建一個CallSite w /一個現有的C#活頁夾。您可以通過在ildasm或反射器中查看「foo.Bar = 42」的結果來獲得此代碼。但是,這是一個簡單的例子是:

object x = new ExpandoObject(); 
CallSite<Func<CallSite, object, object, object>> site = CallSite<Func<CallSite, object, object, object>>.Create(
      Binder.SetMember(
       Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None, 
       "Foo", 
       null, 
       new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) } 
      ) 
     ); 
site.Target(site, x, 42); 
Console.WriteLine(((dynamic)x).Foo); 
+0

我需要一些時間來確定我真的明白這段代碼在做什麼,但無論如何它工作正常......謝謝! – 2010-01-17 16:42:45

+0

使用DLR可以做到<.Net 4.0嗎?看來動態的使用會排除這一點。 – Firestrand 2010-02-03 17:33:08

+0

上述方法不能正常工作。設定器呼叫站點要求被提供,而不是1。正確定義2點參數的相關信息將是:新的[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,空), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,NULL) } – 2011-05-12 14:12:19

5

的開源框架Dynamitey將(通過nuget可用)做到這一點。它封裝,同時仍然緩存@ Dino-Viehland使用的調用網站和綁定代碼。

Dynamic.InvokeSet(foo,"Bar",42); 

它也可以撥打很多other kinds of c# binder too

5

ExpandoObject實現了IDictionary <字符串,對象>雖然明確。這意味着您可以簡單地將ExpandoObject投射到IDictionary <字符串,對象>並操縱字典。

​​
+0

謝謝!事實上ExpandoObject實現了IDictionary,就像我之後意識到的那樣,所以在這種情況下顯然是最簡單的解決方案。然而,我的問題的範圍更廣泛:我正在尋找一種可以與任何動態對象協作的解決方案,而不僅僅是ExpandoObject – 2011-08-14 09:11:12

1

我知道這是一個很老的文章,但我想我會沿着Miron Abramson solution傳授如何創建自己的類型,並在運行時添加的屬性 - 如果任何人在那裏尋找的東西類似。