Kie*_*ton 43 .net c# reflection dynamic
我正在寻找一种方法来修改dynamic
C#4.0对象上的属性,其属性名称仅在运行时已知.
有没有办法做某些事情(ExpandoObject
仅用作示例,这可能是任何实现的类IDynamicMetaObjectProvider
):
string key = "TestKey";
dynamic e = new ExpandoObject();
e[key] = "value";
Run Code Online (Sandbox Code Playgroud)
这相当于:
dynamic e = new ExpandoObject();
e.TestKey = "value";
Run Code Online (Sandbox Code Playgroud)
或者是前进反思的唯一途径?
Jon*_*esø 60
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 16
不是很容易,没有.反射不起作用,因为它假定一个常规类型模型,而不是全范围模型dynamic
.如果你实际上只是在谈论常规对象,那么只需在这里使用反射.否则,我希望您可能需要对编译器为基本分配发出的代码进行反向工程,并将其调整为具有灵活的成员名称.不过我会说实话:这不是一个有吸引力的选择; 一个简单的:
dynamic foo = ...
foo.Bar = "abc";
Run Code Online (Sandbox Code Playgroud)
翻译为:
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");
Run Code Online (Sandbox Code Playgroud)
如果您想要一种适用于动态和非动态对象的方法:FastMember对此非常方便,可以在类型或对象级别工作:
// could be static or DLR
var wrapped = ObjectAccessor.Create(obj);
string propName = // something known only at runtime
Console.WriteLine(wrapped[propName]);
Run Code Online (Sandbox Code Playgroud)
可在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);
}
}
Run Code Online (Sandbox Code Playgroud)
我的开源框架Dynamitey具有使用DLR基于字符串名称进行调用的方法.它完成缓存绑定站点的工作,并将其简化为一个方法调用.它也比非动态对象上的反射运行得更快.
Dynamic.InvokeSet(e, "TestKey", "value");
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
35881 次 |
最近记录: |