c# 4.0 - Using DynamicObject (IDynamicMetaObjectProvider) as a component of a static type leads to infinite loop -
i'm trying create dynamic object can used component of static object. here contrived example of i'm trying accomplish.
here dynamic component:
public class dynamiccomponent : dynamicobject { public override bool tryinvokemember( invokememberbinder binder, object[] args, out object result) { result = "hello"; return true; } }
and here class inheriting dynamicobject
isn't option...assume there third party class i'm forced inherit from.
public class astaticcomponent : vendorlibraryclass, idynamicmetaobjectprovider { idynamicmetaobjectprovider component = new dynamiccomponent(); public dynamicmetaobject getmetaobject(expression parameter) { var result = component.getmetaobject(parameter); return result; } }
the direct usage of dynamiccomponent
works:
dynamic dynamiccomponent = new dynamiccomponent(); assert.areequal(dynamiccomponent.amethod(), "hello");
however, forwarding getmetaobject
through astaticcomponent
causes form of infinite loop.
dynamic dynamiccomponent = new astaticcomponent(); assert.areequal(dynamiccomponent.amethod(), "hello"); //causes infinite loop
anyone know why occurs?
and if it's baked in behavior of dynamicobject
cannot change, provide on how create idynamicmetaobjectprovider
scratch accomplish component based dynamic object (just things started)?
i think problem expression
parameter passed getmetaobject
represents target of dynamic invocation (i.e. current object). passing outer object call on component.getmetaobject
, returned meta object trying resolve call amethod
on outer object instead of itself, hence infinite loop.
you can create own meta object delegates inner component when binding member invocations:
public class astaticcomponent : vendorlibraryclass, idynamicmetaobjectprovider { idynamicmetaobjectprovider component = new dynamiccomponent(); public dynamicmetaobject getmetaobject(expression parameter) { return new delegatingmetaobject(component, parameter, bindingrestrictions.gettyperestriction(parameter, this.gettype()), this); } private class delegatingmetaobject : dynamicmetaobject { private readonly idynamicmetaobjectprovider innerprovider; public delegatingmetaobject(idynamicmetaobjectprovider innerprovider, expression expr, bindingrestrictions restrictions) : base(expr, restrictions) { this.innerprovider = innerprovider; } public delegatingmetaobject(idynamicmetaobjectprovider innerprovider, expression expr, bindingrestrictions restrictions, object value) : base(expr, restrictions, value) { this.innerprovider = innerprovider; } public override dynamicmetaobject bindinvokemember(invokememberbinder binder, dynamicmetaobject[] args) { var innermetaobject = innerprovider.getmetaobject(expression.constant(innerprovider)); return innermetaobject.bindinvokemember(binder, args); } } }
Comments
Post a Comment