gpt4 book ai didi

c#-4.0 - 使用 DynamicObject (IDynamicMetaObjectProvider) 作为静态类型的组件会导致死循环

转载 作者:行者123 更新时间:2023-12-04 17:10:27 25 4
gpt4 key购买 nike

我正在尝试创建一个可用作静态对象组件的动态对象。这是我想要完成的一个人为的例子。

这是动态组件:

public class DynamicComponent : DynamicObject
{
public override bool TryInvokeMember(
InvokeMemberBinder binder,
object[] args,
out object result)
{
result = "hello";
return true;
}
}

这是一个继承自 DynamicObject 的类不是一个选项...假设有一些我被迫继承的第三方类。
public class AStaticComponent : VendorLibraryClass, IDynamicMetaObjectProvider
{
IDynamicMetaObjectProvider component = new DynamicComponent();

public DynamicMetaObject GetMetaObject(Expression parameter)
{
var result = component.GetMetaObject(parameter);

return result;
}
}
DynamicComponent的直接用法作品:
dynamic dynamicComponent = new DynamicComponent();
Assert.AreEqual(dynamicComponent.AMethod(), "hello");

但是,转发 GetMetaObject通过 AStaticComponent导致某种形式的无限循环。
dynamic dynamicComponent = new AStaticComponent();
Assert.AreEqual(dynamicComponent.AMethod(), "hello"); //causes an infinite loop

有谁知道为什么会这样?

如果它是 DynamicObject 的一些行为我无法更改,有人可以就如何创建 IDynamicMetaObjectProvider 提供一些帮助吗?从头开始完成一个基于组件的动态对象(只是让事情开始)?

最佳答案

@Lee 的回答非常有用,如果没有它,我不知道从哪里开始。但是从在生产代码中使用它,我相信它有一个微妙的错误。

动态调用被缓存在调用站点,Lee 的代码生成 DynamicMetaObject它有效地表明内部处理对象是一个常数。如果您的代码中有一个位置可以调用 AStaticObject 实例的动态方法,然后代码中的同一点在 AStaticObject 的不同实例上调用同一方法(即因为 AStaticObject 类型的变量现在具有不同的值)然后代码将进行错误调用,总是从代码运行期间在该位置遇到的第一个实例调用处理对象上的方法。

这是同类替换,主要区别在于使用 Expression.Field告诉动态调用缓存系统处理对象依赖于父对象:

public class AStaticComponent : VendorLibraryClass, IDynamicMetaObjectProvider
{
IDynamicMetaObjectProvider component = new DynamicComponent();

public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new DelegatingMetaObject(parameter, this, nameof(component));
}

private class DelegatingMetaObject : DynamicMetaObject
{
private readonly DynamicMetaObject innerMetaObject;

public DelegatingMetaObject(Expression expression, object outerObject, string innerFieldName)
: base(expression, BindingRestrictions.Empty, outerObject)
{
FieldInfo innerField = outerObject.GetType().GetField(innerFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
var innerObject = innerField.GetValue(outerObject);
var innerDynamicProvider = innerObject as IDynamicMetaObjectProvider;
innerMetaObject = innerDynamicProvider.GetMetaObject(Expression.Field(Expression.Convert(Expression, LimitType), innerField));
}

public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
return binder.FallbackInvokeMember(this, args, innerMetaObject.BindInvokeMember(binder, args));
}
}
}

关于c#-4.0 - 使用 DynamicObject (IDynamicMetaObjectProvider) 作为静态类型的组件会导致死循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17600466/

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