0

I have a dynamic object in C# that I'd like to convert to a static object. I wrote a function that takes the dynamic type and returns the static type, but it actually returns dynamic, ignoring the specified return type. (This is standard behavior, as I've now discovered.) AutoMapper doesn't handle dynamic types. How can I properly convert dynamic to static?

vaindil
  • 7,536
  • 21
  • 68
  • 127
  • 1
    My post specifically says "AutoMapper doesn't handle `dynamic` types", so yes, I've seen it. Is [this answer](https://stackoverflow.com/a/7778398/1672458) outdated? – vaindil Sep 03 '15 at 17:06
  • possible duplicate: http://stackoverflow.com/questions/7778216/automapper-or-similar-allow-mapping-of-dynamic-types – Daniel A. White Sep 03 '15 at 17:07
  • 1
    Can you post sample code? – Ian R. O'Brien Sep 03 '15 at 17:14
  • I have no idea how that answer works, but I guess it is a duplicate. My apologies. – vaindil Sep 03 '15 at 17:15
  • @DanielA.White Actually, that code doesn't work--it returns `dynamic`. Do my `dynamic`s all need to be `expando` for that to work properly? – vaindil Sep 03 '15 at 17:21
  • @Vaindil adding an explicit cast should work: `(T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(dynobj))` – shf301 Sep 03 '15 at 17:58

3 Answers3

3

Using some serializers can be a solution. Suppose you form a dynamic object like

dynamic d = new ExpandoObject();
d.a = 1;
d.b = new ExpandoObject();
d.b.c = "222";

and you want to cast this to A

public class A
{
    public int a { set; get; }
    public B   b { set; get; }
}

public class B
{
    public string c { set; get; }
}

You can use, for example, Json.Net, to do this serialization/deserialization

A a = JsonConvert.DeserializeObject<A>(JsonConvert.SerializeObject(d));
Eser
  • 12,346
  • 1
  • 22
  • 32
0

If you got the type, you can instanciate a new object, then copy the state of your dynamic object into this object with the FormatterServices class:

var staticObject = Activator.CreateInstance(yourType);
MemberInfo[] members = FormatterServices.GetSerializableMembers(yourType);
FormatterServices.PopulateObjectMembers(staticObject, members, 
  FormatterServices.GetObjectData(dynObject, members));
Maxence
  • 12,868
  • 5
  • 57
  • 69
-3

I'm confused... I thought that .NET should already do this for you. Here's some test code and it fits with my expectations:

class Program
{
    static void Main(string[] args)
    {
        dynamic anythingGoes = 1;
        var convertedToInt = ConvertToType<int>(anythingGoes);

        // expectation: should output Int32. and it does....
        Console.WriteLine(convertedToInt.GetType().Name);


        anythingGoes = "ribbit";
        var convertedToString = ConvertToType<string>(anythingGoes);

        // expectation: should output String. and it does also...
        Console.WriteLine(convertedToString.GetType().Name);

        Console.ReadLine();
    }

    // just a small method to cast the dynamic to whatever i want
    // ...only for this test. not guaranteed to be crash safe. in fact, don't assume!
    static T ConvertToType<T>(dynamic obj)
    {
        T result = obj;
        return result;
    }
}
code4life
  • 15,655
  • 7
  • 50
  • 82
  • In Visual Studio put your cursor over `var`. You'll see that it is typed as `dynamic`. The runtime type of convertedString will always be `string` but the compile time type will be `dynamic` which is the issue here. – shf301 Sep 03 '15 at 17:53
  • @EZI: did you? I did, hence the inline comments in my code sample. – code4life Sep 04 '15 at 13:18