can one convert a dynamic object to an ExpandoObject (c#)

15,913

Solution 1

Nope. A dynamic object doesn't enforce the type at compile time, but it doesn't magically make your object expandable (unless it's an ExpandoObject).

You can however, make some kind of wrapper or proxy using DynamicObject... something like:

public class ExpandedObjectFromApi : DynamicObject
{
    private Dictionary<string, object> _customProperties = new Dictionary<string, object>();
    private object _currentObject;

    public ExpandedObjectFromApi(dynamic sealedObject)
    {
      _currentObject = sealedObject;
    }

    private PropertyInfo GetPropertyInfo(string propertyName) 
    { 
       return _currentObject.GetType().GetProperty(propertyName);
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      var prop = GetPropertyInfo(binder.Name);
      if(prop != null)
      {
         result = prop.GetValue(_currentObject);
         return true;
      }
      result = _customProperties[binder.Name];
      return true;          
    }      

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      var prop = GetPropertyInfo(binder.Name);
      if(prop != null)
      {
         prop.SetValue(_currentObject, value);
         return true;
      }
      if(_customProperties.ContainsKey(binder.Name))
        _customProperties[binder.Name] = value;
      else
        _customProperties.Add(binder.Name, value);
      return true;          
    }      
}

And then you can use it like:

dynamic myExpandedObject = new ExpandedObjectFromApi(sealedObject);

This should return the original object properties if found, or if no property of that name is in the original object, it'll add it as a "custom" property.

I've made the code in the Stack Overflow editor and probably made a lot of mistakes, it's not suitable for copy/paste, and it needs tons of error checking (also needs to implement fields and methods, if the received object has them). Just wrote it so you get the basic idea.

You also may want to add a special property (something called WrappedObject, for example) and capture it in TryGetMember, so you can get the original object back.

Solution 2

 ExpandoObject eo=JsonConvert. Deserialize<ExpandoObject>(JsonConvert.Serialize(dynamicObject))

Worked for me to change a dynamic to an ExpandoObject.

Share:
15,913
Dr.YSG
Author by

Dr.YSG

PhD (CS) working in a broad area of technologies: Big Data GPU computing &amp; Non-Von-Neumann programming Cloud Computing Massive distributed gaming (scientific simulations) Computer Vision, Robotics Augmented Reality Mobile GIS 2D/3D Simulation &amp; Virtual Reality serious games 3D Graphics HTML5 for offline mobile apps Data &amp; Info Visualization MultiMedia Real-time collaboration (mobile tech) User Interfaces (video and NUI) as well as Human Centered Design NodeJS,Express, OGMA, Neo4j Graph Database React, Redux, Redux-Thunk, Redux-Form, Electron, the Redux Ecosystem

Updated on June 14, 2022

Comments

  • Dr.YSG
    Dr.YSG about 2 years

    I am getting an dynamic object of type "Sealed Class" from a driver api (in dll). I want to decorate this object with a few additional properties.

    I would like to do something to the effect of:

    public void expandIT(dynamic sealedObject) {
    
        ExpandoObject expand = new ExpandoObject(sealedObject);
        expand.time = DateTime.Now();
        etc....
    }
    

    UPDATE

    I like JCL's solution. But for what I wanted to do, it was easier to create a ExpandoObject and then embed the Dynamic sealed class object as a child property, and then add my properties to the parent ExpandoObject. Thanks JCL, I was in brain-freeze as to how to do this. I

  • Jcl
    Jcl about 8 years
    If you implement something like this and you need performance, just as a suggestion, I'd make some kind of cache for the PropertyInfo returned by GetPropertyInfo. Reflection is always a bit slow :-)
  • toughQuestions
    toughQuestions over 4 years
    It seems that you are only compiling the ExpandoObject out of properties. How about methods?
  • Jcl
    Jcl over 4 years
    @toughQuestions yes, that's on the note below the code ((also needs to implement fields and methods, if the received object has them)), this was some simple code made in the SO editor and not intended to copy&paste, just giving out the idea
  • toughQuestions
    toughQuestions over 4 years
    Could you provide an example that sets methods by any chance?
  • Jcl
    Jcl over 4 years
    @toughQuestions not right now, but it'd be just overriding TryInvokeMember (docs) (same as we do with TryGetMember), and call InvokeMember (docs) on _currentObject.GetType()