title: Automapper: Mapping using attributes for non-matching properties
body: <p>I have a scenario in which I'm creating a mapping utility through which we can map <code>DataReader</code> to entities. </p>
  
  
  
  <pre class="lang-cs prettyprint-override"><code>Mapper.CreateMap&lt;IDataReader, T&gt;();
  List&lt;T&gt; tList = Mapper.Map&lt;List&lt;T&gt;&gt;(reader);
  return tList;
  </code></pre>
  
  <p>This is working fine if the entity has same columns as in the stored procedure's output. However, I'm working on an some old code where column names are not matching. So I created an attribute through which I could specify corresponding column from sprocs. I specify them using code like this</p>
  
  <pre class="lang-cs prettyprint-override"><code>[DBColumn('EmployeeName')]
  public string EmpName { get; set; }
  </code></pre>
  
  <p>Is there any way I can achieve this using generics/reflection? Note that I have multiple such instances and I'm building an utility. So I can not use <code>ForMember</code> method to achieve that.</p>
  
  <p>UPDATE: I tried creating  a custom converter like this. However, my convert function is not getting called at all.</p>
  
  <p>Custom converter </p>
  
  <pre class="lang-cs prettyprint-override"><code>public class CustomConverter&lt;T&gt; : ITypeConverter&lt;System.Data.IDataReader, T&gt;
  {
      private ResolutionContext _Context = null;
      private Dictionary&lt;string, string&gt; _CustomProps { get; set; }
      public T Convert(ResolutionContext context)
      {
          _Context = context;
  
          if (_Context.SourceValue != null &amp;&amp;
              !(_Context.SourceValue is System.Data.IDataReader))
          {
              string message = "Value supplied is of type {0} but expected {1}.\n" +
                               "Change the type converter source type, or redirect " +
                               "the source value supplied to the value resolver using FromMember.";
  
              throw new AutoMapperMappingException(_Context, string.Format(
                  message, typeof(System.Data.IDataReader), _Context.SourceValue.GetType()));
          }
          _CustomProps = new Dictionary&lt;string, string&gt;();
          foreach (PropertyInfo propInfo in context.DestinationType.GetProperties())
          {
              if (propInfo.CustomAttributes.Any(attr =&gt; attr.AttributeType == typeof(DBColumn)))
              {
                  DBColumn propertyValue = (DBColumn)propInfo.GetCustomAttribute(typeof(DBColumn));
                  _CustomProps.Add(propertyValue.ColumnName, propInfo.Name);
              }
          }
          //return base.Convert(context);            
          return ConvertCore((System.Data.IDataReader)context.SourceValue);
      }
  
      protected T ExistingDestination
      {
          get
          {
              if (_Context == null)
              {
                  string message = "ResolutionContext is not yet set. " +
                                   "Only call this property inside the 'ConvertCore' method.";
  
                  throw new InvalidOperationException(message);
              }
  
              if (_Context.DestinationValue != null &amp;&amp;
                  !(_Context.DestinationValue is T))
              {
                  string message = "Destination Value is of type {0} but expected {1}.";
  
                  throw new AutoMapperMappingException(_Context, string.Format(
                      message, typeof(T), _Context.DestinationValue.GetType()));
              }
  
              return (T)_Context.DestinationValue;
          }
      }
  
      protected T ConvertCore(System.Data.IDataReader source)
      {
          T obj = ExistingDestination;
          if (obj != null)
          {
              foreach (KeyValuePair&lt;string, string&gt; keyValuePair in _CustomProps)
              {
                  PropertyInfo prop = obj.GetType().GetProperty(keyValuePair.Key,  BindingFlags.Public | BindingFlags.Instance);
                  if (null != prop &amp;&amp; prop.CanWrite)
                  {
                      prop.SetValue(obj, System.Convert.ChangeType(source[keyValuePair.Value], prop.PropertyType));
                  }
              }
          }
          return obj;
      }
  </code></pre>
  
  <p>I'm specifying to use this CustomConverter in below statement.</p>
  
  <pre class="lang-cs prettyprint-override"><code>        Mapper.CreateMap&lt;IDataReader, T&gt;().ConvertUsing&lt;CustomConverter&lt;T&gt;&gt;();
          List&lt;T&gt; tList = Mapper.Map&lt;List&lt;T&gt;&gt;(reader);
          return tList;
  </code></pre>
  
  <p>Please let me know, where I'm going wrong</p>