Is there a way to convert a dynamic or anonymous object to a strongly typed, declared object?
Asked Answered
P

5

61

If I have a dynamic object, or anonymous object for that matter, whose structure exactly matches that of a strongly typed object, is there a .NET method to build a typed object from the dynamic object?

I know I can use a LINQ dynamicList.Select(dynamic => new Typed { .... } type thing, or I can use Automapper, but I'm wondering if there is not something specially built for this?

Pejsach answered 14/6, 2013 at 4:38 Comment(0)
M
71

You could serialize to an intermediate format, just to deserialize it right thereafter. It's not the most elegant or efficient way, but it might get your job done:

Suppose this is your class:

// Typed definition
class C
{
    public string A;
    public int B;
}

And this is your anonymous instance:

// Untyped instance
var anonymous = new {
    A = "Some text",
    B = 666
};

You can serialize the anonymous version to an intermediate format and then deserialize it again to a typed version.

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(anonymous);
var c = serializer.Deserialize<C>(json);

Note that this is in theory possible with any serializer/deserializer (XmlSerializer, binary serialization, other json libs), as long as the roundtrip is symmetric.

Maitund answered 26/6, 2013 at 14:5 Comment(5)
+1. Nice thought, even though it uses reflection behind the scenes.Spermary
Have been giving this some thought: I guess you'll always have an intermediate representation when you would go about this and you would always have reflection on both ends (anonymous and typed object). So I guess in order to optimize this, you just need to find the most efficient intermediate form: servicestack.net/benchmarksMaitund
perhaps also learn.microsoft.com/en-us/dotnet/api/…Tedmann
Bringing string manipulation into it means taking a serious performance hit.Mig
@JonathanByrne may be true. Although if you're interested in squeezing performance, then you shouldn't be doing this in the first place. But as said, it's also possible to rely on more efficient (de)serializers.Maitund
S
19

Your question comes down to the question: can I convert one statically typed variable into another statically typed variable (from different inheritance chains)? and the answer, obviously, is No.

Why does your question come down to the above question?

  • Dynamic type usage compiles into using the Object type with reflection.
  • Your code receives Object in reality, that (in reality) contains value from one particular static type.

So, in fact, your code is dealing with the statically typed value, assigned to the Object, and treated as Dynamic at compile time. Therefore, the only case when you can convert one statically typed value into another [without reflection] is when they are part of the same inheritance chain. Otherwise, you are bound to using reflection explicitly (written by you) or implicitly (written by MS with Dynamic usage).

In other words, the following code will work at runtime only if the value assigned to the dynamic is derived from Person or is Person itself (otherwise the cast to Person will throw an error):

dynamic dPerson = GetDynamicPerson();
Person thePerson = (Person)dPerson;

That's pretty much it.

Fair to mention, you can copy the values byte by byte with unsafe code accessing the memory addresses (like in C++), but that to me is nothing better than reflection.

Spermary answered 25/6, 2013 at 16:47 Comment(1)
But so much more adventurous than reflection :-)Pejsach
D
8

Here we can convert an anonymous object to Dictionary

Dictionary<string, object> dict = 
    obj.GetType()
      .GetProperties()
      .ToDictionary(p => p.Name,  p => p.GetValue(obj, null));

Also you can cast an object using LINQ:

List<MyType> items = anonymousType.Select(t => new MyType(t.Some, t.Other)).ToList();
Discreet answered 25/6, 2013 at 17:57 Comment(1)
This is the fastest solution here.Pouf
M
1

If your object inherits from MarshalByRefObject you can use RealProxy.

Another alternative is to use Reflection but you may be limited by stuff not marked virtual and/or have to use interfaces. You could also have it copy the values, assuming the properties are writable and the empty constructor works for your case.

The actual answer to your question is no, there is no automatic way to treat a dynamic object as a specific type unless it is an instance of that type, nor is there any automatic facility to copy the values from a dynamic/anonymous object into an instance of a named class.

The runtime has no idea what is going on in the constructor or how the class is implemented internally, so any such facility would blow type safety out of the water. The whole point of dynamic is to allow duck typing/runtime dispatch/etc.

edit: If I misunderstood the question let me know, but I am assuming you want to treat a dynamic object as if it were an instance of SomeType.

In my own projects, I've used an Object Mapper class for this where it matches up the property names for writable properties and identical or coercible types so at least I didn't have to write 10,000 lines of boilerplate, though my source wasn't dynamic so I used Reflection.Emit/DynamicMethod to greatly speed it up.

Mayorga answered 24/6, 2013 at 5:32 Comment(2)
You did slightly misunderstand me. I don't want to automatically treat a dynamic object as a statically typed object. I want to convert a dynamic object to a statically typed object. The use cases will probably be mainly for dynamic DTOs and such, so constructor logic isn't as big a risk factor as it could be.Pejsach
Ok, sorry about that; there is no automatic way to do it. jherax' solution works to convert to a dictionary obviously, but reflection will be slow. In my scenario, I created an ObjectMapper that caches a DynamicMethod (built using emitted IL) that copies between the types so it is extremely fast after first use, but we have a ton of DTO types. For a dynamic object that won't work, though there are some potential speedups if you need it.Mayorga
J
0

So, I am going to provide an answer to this question that assumes you will manually set the primitive variables. Say you have a Dictionary<string, dynamic> dict that contains the dynamic version of float x and a bool y. You can do:

float x = (float)dict["x"];
bool y = (bool)dict["y"];

If you wanted to do this for reference types, you can simply have a constructor for your class that does this conversion for every field.

Julejulee answered 17/2, 2022 at 18:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.