gpt4 book ai didi

.net - 如何直接调用 DynamicObject.TryGetMember?

转载 作者:行者123 更新时间:2023-12-03 10:19:40 24 4
gpt4 key购买 nike

我正在实现一个通用函数来从任意提供的动态对象中提取一个值,但不知道如何调用 TryGetMember因为它需要 GetMemberBinder这是抽象的,因此我无法创建它。
样本...

public object GetValue(DynamicObject Source, string FieldName)
{
object Result = null;
GetMemberBinder Binder = x; // What object must be provided?
Binder.Name = FieldName;
if (Source.TryGetMember(Binder, out Result))
return Result;

throw new Exception("The field '" + FieldName + "' not exists");
}

是否已经存在 GetMemberBinder 的具体后代可供使用?或创建我自己的实现的指南?

最佳答案

我不确定框架中是否有任何方法实际返回 GetMemberBinder ,但没关系 - 这不是按名称调用动态成员的正确方法。

您实际需要做的是创建一个调用站点。该方法如下所示:

static object GetDynamicMember(object obj, string memberName)
{
var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, obj.GetType(),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var callsite = CallSite<Func<CallSite, object, object>>.Create(binder);
return callsite.Target(callsite, obj);
}

请注意 Binder.GetMember创建一个 CallSiteBinder , 不是 一个 GetMemberBinder .只是为了100%清楚。此方法将抛出 RuntimeBinderException如果内部调用 TryGetMember失败,因此您无需检查结果。如果您不希望来电者看到 RuntimeBinderException然后将其包装在您自己的 try/catch 中。

动态调度是复杂的,至少相对于静态类型的反射而言。由于 CLR 实际上不是动态类型的,因此 C# 必须实际实例化一个编译器来确定如何执行成员/方法。那就是创建一个调用站点。据我所知,你必须这样做,这就是为什么每个 Binder方法返回 CallSiteBinder而且您不能直接实例化任何活页夹。

请注意,DLR 会进行某种调用站点缓存,但我不确定自动缓存是否涵盖这种情况。您很有可能希望保存您的调用站点以供将来调用,以避免不断重新编译的开销。

附言如果您正在使用(或可以使用) ExpandoObject而不是 DynamicObject然后记住它实现了 IDictionary<string, object> ,所以你不需要做任何这些。只需将其转换为字典类型并检查该属性是否存在。我只会使用 DynamicObject超过 ExpandoObject如果我做的事情比简单地在运行时添加成员要复杂得多,即根据运行时绑定(bind)器更改实际行为。

关于.net - 如何直接调用 DynamicObject.TryGetMember?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5306018/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com