title: Mapping Dynamic ExpandoObject To Object
body: <p>Recently I had to use ExpandoObject in my application, So I want to know how could I use my old Mapper to also map from Dynamic ExpandoOnjects, because some how it does not map the fields, and properties from an Expando.</p>
  
  <p><strong>Code</strong>:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Reflection;
  
  public class Mapper
  {
      private static readonly Dictionary&lt;KeyValuePair&lt;Type, Type&gt;, object&gt; Maps = new Dictionary&lt;KeyValuePair&lt;Type, Type&gt;, object&gt;();
  
      private static PropertyInfo[] _fromProperties;
      private static PropertyInfo[] _toProperties;
      private static FieldInfo[] _fromFields;
      private static FieldInfo[] _toFields;
  
      // Rules...
      private static readonly Func&lt;PropertyInfo, PropertyInfo, bool&gt; MatchingProps = (t1, t2) =&gt; t1.Name == t2.Name &amp;&amp; t1.PropertyType.Name == t2.PropertyType.Name;
      private static readonly Func&lt;FieldInfo, FieldInfo, bool&gt; MatchingFields = (t1, t2) =&gt; t1.Name == t2.Name &amp;&amp; t1.FieldType.Name == t2.FieldType.Name;
      private static readonly Func&lt;PropertyInfo, FieldInfo, bool&gt; MatchingPropertyToField = (t1, t2) =&gt; t1.Name == t2.Name &amp;&amp; t1.PropertyType.Name == t2.FieldType.Name;
      private static readonly Func&lt;FieldInfo, PropertyInfo, bool&gt; MatchingFieldToProperty = (t1, t2) =&gt; t1.Name == t2.Name &amp;&amp; t1.FieldType.Name == t2.PropertyType.Name;
  
      public static void AddMap&lt;TFrom, TTo&gt;(Action&lt;TFrom, TTo&gt; map = null)
              where TFrom : class
              where TTo : class { Maps.Add(new KeyValuePair&lt;Type, Type&gt;(typeof(TFrom), typeof(TTo)), map); }
  
      public static void Map&lt;TFromType, TOType&gt;(TFromType @from, TOType to)
      {
          var key = new KeyValuePair&lt;Type, Type&gt;(typeof(TFromType), typeof(TOType));
          var map = (Action&lt;TFromType, TOType&gt;)Maps[key];
  
          bool hasMapping = Maps.Any(x =&gt; x.Key.Equals(key));
  
          if (!hasMapping)
              throw new Exception(string.Format("No map defined for {0} =&gt; {1}", typeof(TFromType).Name, typeof(TOType).Name));
  
          Type tFrom = typeof(TFromType);
          Type tTo = typeof(TOType);
  
          _fromProperties = tFrom.GetProperties();
          _fromFields = tFrom.GetFields();
          _toProperties = tTo.GetProperties();
          _toFields = tTo.GetFields();
  
          SyncProperties(@from, to);
          SyncFields(@from, to);
  
          if (!Equals(map, null))
              map(@from, to);
      }
  
      private static void SyncProperties&lt;TFromType, TOType&gt;(TFromType objFrom, TOType objTo)
      {
          PropertyInfo[] fromProperties = _fromProperties;
          PropertyInfo[] toProperties = _toProperties;
          FieldInfo[] toFields = _toFields;
  
          if (fromProperties != null &amp;&amp; fromProperties.Any()) {
              foreach (PropertyInfo fromProperty in fromProperties) {
                  if (toProperties.Any(x =&gt; x.Name == fromProperty.Name)) {
                      PropertyInfo destinationProperty = toProperties.FirstOrDefault(x =&gt; x.Name == fromProperty.Name);
  
                      if (MatchingProps(fromProperty, destinationProperty)) {
                          object val = fromProperty.GetValue(objFrom, null);
                          if (Equals(val, null)) continue;
                          if (!Equals(destinationProperty, null)) destinationProperty.SetValue(objTo, Convert.ChangeType(val, fromProperty.PropertyType), null);
                      }
                  }
  
                  if (toFields.Any(x =&gt; x.Name == fromProperty.Name)) {
                      FieldInfo destinationField = toFields.FirstOrDefault(x =&gt; x.Name == fromProperty.Name);
  
                      if (MatchingPropertyToField(fromProperty, destinationField)) {
                          object val = fromProperty.GetValue(objFrom, null);
                          if (Equals(val, null)) continue;
                          if (!Equals(destinationField, null)) destinationField.SetValue(objTo, val);
                      }
                  }
              }
          }
      }
  
      private static void SyncFields&lt;TFromType, TOType&gt;(TFromType objFrom, TOType objTo)
      {
          FieldInfo[] fromFields = _fromFields;
          FieldInfo[] toFields = _toFields;
          PropertyInfo[] toProperties = _toProperties;
  
          if (fromFields != null &amp;&amp; fromFields.Any()) {
              foreach (FieldInfo fromField in fromFields) {
                  if (toFields.Any(x =&gt; x.Name == fromField.Name)) {
                      FieldInfo destinationField = toFields.FirstOrDefault(x =&gt; x.Name == fromField.Name);
  
                      if (MatchingFields(fromField, destinationField)) {
                          object val = fromField.GetValue(objFrom);
                          if (Equals(val, null)) continue;
                          if (!Equals(destinationField, null)) destinationField.SetValue(objTo, val);
                      }
                  }
  
                  if (toProperties.Any(x =&gt; x.Name == fromField.Name)) {
                      PropertyInfo destinationProperty = toProperties.FirstOrDefault(x =&gt; x.Name == fromField.Name);
  
                      if (MatchingFieldToProperty(fromField, destinationProperty)) {
                          object val = fromField.GetValue(objFrom);
                          if (Equals(val, null)) continue;
                          if (!Equals(destinationProperty, null)) destinationProperty.SetValue(objTo, val, null);
                      }
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>Usage</strong>:</p>
  
  <pre><code>static void Main()
  {
      dynamic o = new ExpandoObject();
      o.Name = "Pouce";
      o.Age = 42;
      o.Rank = new Rank
               {
                       Name = Ranks.Major
               };
      o.Guid = new Guid();
  
      Soldier soldier = new Soldier();
      Mapper.AddMap&lt;ExpandoObject, Soldier&gt;();
      Mapper.Map(o, soldier);
  
      Console.ReadLine();
  }
  
  public class Soldier
  {
      public string Name { get; set; }
      public int Age { get; set; }
      public Rank Rank { get; set; }
      public Guid Guid { get; set; }
  }
  
  public class Rank
  {
      public Ranks Name { get; set; }
  }
  
  public enum Ranks
  {
      Private,
      Specialist,
      Corporal,
      Sergeant,
      Captain,
      Major,
      Colonel,
      General
  }
  </code></pre>
  
  <ul>
  <li>[Q] : How could I use my mapper (presented above) to map from the
  dynamic ExpandoObject.</li>
  <li>[P] : The problem is that it works perfectly in normal <code>&lt;object,
  object&gt;</code> mapping; However when provided with <code>&lt;ExpandoObject, object&gt;</code>
  it does not map anything.</li>
  </ul>