Define a computed property of an expando object

I am working with an expando object and I am trying to define a computed property.

I know that I can define a simple property by doing something like the following:

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

Similarly, I can also define a method:

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

When working with a standard object, we can define a computed property, that is, define a property that will return the results of a custom / calc method. No need for this example.

I need to do something similar on my expando - having a property that actually calls "Func" (or some other delegate form, everything goes as soon as I can call the user method and have its own return type). Therefore, basically I need to call the method, as in the second example, but to work as a property.

Basically I need to be able to call it myExpando.GetTheQuestion instead of myExpando.GetTheQuestion () , while maintaining the ability to define a custom delegate as a property of the body.

Is there any way to do this? I believe that I can do this using expression trees, but I admit that I got a little lost there. Can someone give some recommendations on how to achieve this?


EDIT

Come up with some more research .. If there is no special class / interface / syntax that I do not know, I begin to think that this is impossible. From what I get, the ExpandoObject class works by defining some methods that make the background water supply - TryGetMember, TrySetMember, etc. Now that there is “access to the property” in the dynamic object, TryGetMember is the memeber that is being called. This member returns a value from a kind of internal dictionary (yes, I know ... this is a little simplified, but should give an idea) ... there is no test for the type of the return value. This means that in my example, myExpando.GetTheQuestion will return the original Func.

It would seem that since TryGetMember simply returns a value, there is no way to make it "execute" the property code. To do this, you need some surrogate expression / lambda / func / action, the value of which is actually the RESULT of the method. Which seems impossible (and it won’t make much sense if I don’t miss something - basically you will have a value that is set as a “delegate”, and then it turns out as the return value of a delegate ???). Is this right, or am I missing something?

+7
source share
1 answer

You need to create your own ExpandoObject, inheriting DynamicObject and overriding

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

TrySetMember to store the value in a closed Dictionary<string,object> under binder.Name and use TryGetMember to extract it from this dictionary, which will give you the base ExpandoObject. Then, to give it the necessary function, add a TryGetMember check after you pull the object to see if it is Delagate , and then use reflection to see if it accepts any arguments. If both truths are simply passed to dynamic and do not add the arg parenthesis and assign its 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)(); } } } 

I have an open source framework ImpromptuInterface (in nuget) that has an unsealed ImpromptuDictionary that you can start with your ExpandoObject , especially if you need some more subtle ExpandoObject functions such as gui binding support. It also has more dlr plumbing features that you might need.

+2
source

All Articles