agileobjects / AgileMapper

A zero-configuration, highly-configurable, unopinionated object mapper with viewable execution plans. Flattens, unflattens, deep clones, merges, updates and projects queries. .NET 3.5+ and .NET Standard 1.0+.
MIT License
460 stars 27 forks source link

Error trying to map from a dynamic #227

Closed simax closed 2 years ago

simax commented 2 years ago

https://dotnetfiddle.net/Dh3uCR

I'm just starting to play around with this package because it looks really useful. But I hit a problem when trying out the example regarding mapping dynamic/expando objects that I copied from the docs.

using System;
using System.Collections.Generic;
using System.Dynamic;
using AgileObjects.AgileMapper;

public class Doctor
{
    public string Name { get; set; }
    public string[] PhoneNumbers { get; set; }
    public IReadOnlyCollection<Specialty> Specialties { get; set; }
}
public class Specialty
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Program
{
    public static void Main()
    {
            dynamic source = new ExpandoObject();
            source.Name = "Andy";
            source.PhoneNumbers_0 = "01234 567890";
            source.PhoneNumbers_1 = "07890 654321";
            source.Specialties_0_Id = 123;
            source.Specialties_0_Name = "Emergency Medicine";
            source.Specialties_1_Id = 456;
            source.Specialties_1_Name = "Critical Care";

            Doctor doctor = Mapper.Map(source).ToANew<Doctor>();
        Console.WriteLine($"Doctor : {doctor.Name}");
    }
}

Running the code produces:

Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'ToANew'
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at Program.Main()
Command terminated by signal 6

What am I missing?

SteveWilkes commented 2 years ago

Hi!

Dynamic has different levels of support between runtimes - .NET Standard 1.0 supports mapping nested dynamic members, but gives the error you encountered if you try to map a dynamic object 'directly'. Here's an updated fiddle successfully mapping the dynamic as a nested member with AgileMapper v1.8.1.

I'd have thought .NET 6 would use the .NET Standard 1.3 version of the package - which supports both scenarios - so I'm not sure what's going on at runtime on .NET Fiddle. Here's the result of running the same code in a .NET 6 unit test project in VS2022:

image

Hope that helps!

All the best,

Steve

simax commented 2 years ago

OK, thanks for quick response and congrats on the project.