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