gpt4 book ai didi

c# - 在 expando 对象上定义计算属性

转载 作者:太空狗 更新时间:2023-10-29 20:36:56 24 4
gpt4 key购买 nike

我正在使用 expando 对象,我正在尝试定义一个计算属性。

我知道我可以通过执行以下操作来定义一个简单的属性:

dynamic myExpando = new ExpandoObject();
myExpando.TheAnswerToLifeTheUniverseAndEverything= 42;

同样,我也可以定义一个方法:

myExpando.GetTheQuestion = ((Func<string>)(() =>
{
return "How many road must a man walk down before we can call him a man?";
}));

在使用标准对象时,我们可以定义一个计算属性,即定义一个将返回自定义方法/计算结果的属性。无需示例。

我需要在我的 expando 上做一些类似的事情——拥有一个实际调用“Func”的属性(或其他形式的委托(delegate),只要我可以调用自定义方法并具有自定义返回类型,任何事情都会发生)。所以基本上我需要调用第二个示例中的方法,但让它像属性一样工作。

基本上,我需要能够使用 myExpando.GetTheQuestion 而不是 myExpando.GetTheQuestion() 来调用它,同时保持将自定义委托(delegate)定义为属性的能力 body 。

有没有办法做到这一点?我相信我可以通过使用表达式树来做到这一点,但我承认我在那里有点迷路。谁能就如何实现这一目标提供一些指导??


编辑

做了更多的研究。除非有一些我不知道的非常具体的类/接口(interface)/语法,否则我开始认为以上是不可能的。据我所知,ExpandoObject 类通过定义一些执行后台管道的方法来工作 - TryGetMember、TrySetMember 等。现在,当在动态对象上“访问属性”时,TryGetMember 是被调用的成员。该成员从某种内部字典返回一个值(是的,我知道......这有点简化但应该给出想法)......没有对返回值的类型进行测试。这意味着在我的示例中 myExpando.GetTheQuestion 将返回原始 Func。

看来,由于 TryGetMember 只是返回一个值,因此没有办法让它“执行”属性代码。为此,您需要某种表达式/lambda/func/action 代理,哪个值实际上是方法的结果。这似乎是不可能的(也没有多大意义,除非我错过了什么——基本上你会有一个设置为“委托(delegate)”的值,然后作为委托(delegate)返回值获取???)。我是正确的还是这个或者我遗漏了什么?

最佳答案

您需要通过继承 DynamicObject 来创建自己的 ExpandoObject并覆盖

public override bool TryGetMember(GetMemberBinder binder, out object result)public override bool TrySetMember(SetMemberBinder binder, object value)

实现 TrySetMember将值存储在私有(private) Dictionary<string,object> 中在 binder.Name 下并使用 TryGetMember从该字典中检索它,这将为您提供一个基本的 ExpandoObject。然后给它你需要的功能,添加检查 TryGetMember , 拉动物体后,看它是否is Delagate然后使用反射来查看它是否不接受任何参数。如果两者都为真,则转换为 dynamic并且不添加 arg 调用括号并将其分配给 result .

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_dictionary.TryGetValue(binder.Name, out result)){
if(result is Delegate && /* some reflection check on args*/){
result = ((dynamic)result)();
}
}
}

我有一个开源框架 ImpromptuInterface(在 nuget 中),它有一个非密封 ImpromptuDictionary您可以从 ExpandoObject 开始相反,特别是如果您需要 ExpandoObject 的任何更细微的功能时例如 gui 绑定(bind)支持。它还有更多 dlr plumbing features你可能会觉得有用。

关于c# - 在 expando 对象上定义计算属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14816391/

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