![](/img/trans.png)
[英]In C# .NET, how do you access a property of an object when you know another property of an object?
[英]How to set a property of a C# 4 dynamic object when you have the name in another variable
我正在尋找一種方法來修改dynamic
C# 4.0 object 上的屬性,其屬性名稱僅在運行時已知。
有沒有辦法做類似的事情( ExpandoObject
僅用作示例,這可以是實現IDynamicMetaObjectProvider
的任何 class ):
string key = "TestKey";
dynamic e = new ExpandoObject();
e[key] = "value";
這相當於:
dynamic e = new ExpandoObject();
e.TestKey = "value";
還是反思是唯一的出路?
Paul Sasik在C#4.0 Dynamic vs Expando上回答了類似的問題......他們在哪里適合?
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
var p = expando as IDictionary<String, object>;
p["A"] = "New val 1";
p["B"] = "New val 2";
Console.WriteLine(expando.A);
Console.WriteLine(expando.B);
}
}
不是很容易,沒有。 反射不起作用,因為它假設一個常規類型模型,這不是 dynamic
的全部范圍。 如果你實際上只是在談論常規對象,那么只需在這里使用反射。 否則,我希望您可能需要對編譯器為基本分配發出的代碼進行反向工程,並將其調整為具有靈活的成員名稱。 不過我會說實話:這不是一個有吸引力的選擇; 一個簡單的:
dynamic foo = ...
foo.Bar = "abc";
翻譯為:
if (<Main>o__SiteContainer0.<>p__Site1 == null)
{
<Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "Bar", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
}
<Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, foo, "abc");
如果您想要一種適用於動態和非動態對象的方法: FastMember對此非常方便,可以在類型或對象級別工作:
// could be static or DLR
var wrapped = ObjectAccessor.Create(obj);
string propName = // something known only at runtime
Console.WriteLine(wrapped[propName]);
可在Nuget上使用,並針對動態和非動態場景進行了大量優化。
要添加Jonas的答案,您不必創建新的var p。 改為使用這種方法:
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic expando = new ExpandoObject();
((IDictionary<String, object>)expando)["A"] = "New val 1";
((IDictionary<String, object>)expando)["B"] = "New val 2";
Console.WriteLine(expando.A);
Console.WriteLine(expando.B);
}
}
我的開源框架Dynamitey具有使用DLR基於字符串名稱進行調用的方法。 它完成緩存綁定站點的工作,並將其簡化為一個方法調用。 它也比非動態對象上的反射運行得更快。
Dynamic.InvokeSet(e, "TestKey", "value");
快速成員可能適合賬單 - 它看起來像是在運行中生成IL,但是緩存它所以它在第一次使用后真的很快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.