Search code examples
c#jsonravendbexpando

Deserialize an anonymous type into a dynamic


I have an application that contains a business entity called a 'Task'. This entity has a fixed set of properties, but also the ability to behave as an expando.

So, its schema looks like this:

namespace RavenResearch
{
    public class Task
    {
        public Guid TaskId { get; set; }
        public DateTime CreatedDate { get; set; }
        public dynamic DynamicProperties { get; set; }
    }
}

When this is stored in RavenDB, it look liks this

{
  "TaskId": "9cac592f-98ec-4fda-a823-e5402736078e",
  "CreatedDate": "2011-09-22T10:25:35.2701544+12:00",
  "DynamicProperties": {
    "$type": "<>f__AnonymousType0`2[[System.Int32, mscorlib],[System.String, mscorlib]], RavenResearch",
    "MatterNumber": 0,
    "CustomerNumber": "37"
  }
}

Of course, when I attempt to query this datastore from ANOTHER program, it attempts to look for an anonymous type containing an int and string. That other program is the EXE which saved the document originally - I dont want to have to reference this.

What would be the best way to pull out the dynamic properties? My goal is to be able to query a list of Task objects from Raven, and pass them to Xaml for rendering in the UI - which is why databinding to an Expando is so attractive to me, the properties need not be known at compile time.

I create instances (to store in Raven) with statements like this

new RavenResearch.Task()
{
    TaskId = Guid.NewGuid(),
    CreatedDate = DateTime.Now,
    DynamicProperties = new 
    {
        MatterNumber = 0,
        CustomerNumber = "37"
    }
}

@Jacob: I would lose all type information about the dynamic properties if I used a dictionary - however, I could do something like this:

public class Task
{
    public Guid TaskId { get; set; }
    public DateTime CreatedDate { get; set; }
    public Dictionary<string, SimpleValue> DynamicProperties { get; set; }
}

public abstract class SimpleValue
{

}

public class SimpleValue<T> : SimpleValue
{
    public T Value
    { get; set; }

    public SimpleValue(T value)
    {
        this.Value = value;
    }
}

Solution

  • Maybe avoiding using dynamic is best in this case. If you use a Dictionary<string, object> instead, creating a Task wouldn't be too horrible:

    new RavenResearch.Task {
        TaskId = Guid.NewGuid(),
        CreatedDate = DateTime.Now,
        DynamicProperties = new Dictionary<string, object> {
            { "MatterNumber", 0 },
            { "CustomerNumber", "37" } 
        }
    }