如何在另一个variables中具有名称时设置C#4dynamic对象的属性

我正在寻找一种方法来修改dynamic C#4.0对象的属性,只有在运行时才知道该属性的名称。

有没有办法做一些像( ExpandoObject只是作为一个例子,这可能是实现IDynamicMetaObjectProvider任何类):

 string key = "TestKey"; dynamic e = new ExpandoObject(); e[key] = "value"; 

这将相当于:

 dynamic e = new ExpandoObject(); e.TestKey = "value"; 

或者是唯一的前瞻性思考方式?

不是很容易,不。 reflection不起作用,因为它假设了一个常规的types模型,而不是全部的dynamic 。 如果你实际上只是在和普通物体交谈,那么就在这里使用reflection。 否则,我希望你可能需要对编译器发出的代码进行反向工程,然后将其调整为具有灵活的成员名称。 不过,老实说,这不是一个有吸引力的select。 一个简单的:

 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"); 

如果您想要一个适用于dynamic和非dynamic对象的方法: FastMember适用于此,并且可以在types或对象级别上工作:

 // could be static or DLR var wrapped = ObjectAccessor.Create(obj); string propName = // something known only at runtime Console.WriteLine(wrapped[propName]); 

在Nuget上可用,并针对dynamic和非dynamicscheme进行了大量优化。

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); } } 

要添加到Jonas的答案,你不必创build一个新的变种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根据string名称调用的方法。 它完成caching绑定站点的工作,并将其简化为一个方法调用。 它也比在非dynamic对象上的reflection运行得更快。

 Dynamic.InvokeSet(e, "TestKey", "value"); 

快速成员可能适合账单 – 它看起来像它在飞行中产生的IL,但caching,所以它是第一次使用后真的很快。