title: Using AutoMapper Custom Value Resolver for Multiple Members
body: <p>I am attempting to resolve member data located in the source type to a member in the destination type by using the Custom Value Resolver methodology. I have followed as closely as possible the documentation on the AutoMapper website at <a href="http://docs.automapper.org/en/stable/Custom-value-resolvers.html" rel="nofollow noreferrer">http://docs.automapper.org/en/stable/Custom-value-resolvers.html</a>. I have checked carefully to ensure that I am following the example provided, however with one difference. The member on the source is of a different type than the member on the destination.</p>
  
  <p><code>IValueResolver.cs</code></p>
  
  <pre><code>public interface IValueResolver&lt;in TSource, in TDestination, in TSourceMember, TDestinationMember&gt;
  {
      TDestinationMember Resolve(TSource source, TDestination destination, TSourceMember sourceMember, TDestinationMember destinationMember, ResolutionContext context);
  }
  </code></pre>
  
  <p><code>DisplayIdResolver.cs</code></p>
  
  <pre><code>public class DisplayIdResolver : IValueResolver&lt;object, object, int, string&gt;
  {
      // Seems like this may be useless unless its mapping to a destination member of the same type as the source member
      public string Resolve(object source, object destination, int sourceMember, string destinationMember, ResolutionContext context)
      {
          if (source.GetType().Equals(typeof(Developer)))
          {
              return IdentifierType.ConvertToAppId(sourceMember, IdentifierType.DEVELOPER.Code);
          }
          . . . etcetera . . .
       }
  }
  </code></pre>
  
  <p><code>AutoMapperProfile.cs</code></p>
  
  <pre><code>public class AutoMapperProfile : Profile
  {
      public AutoMapperProfile()
      {
          CreateMap&lt;Developer, DeveloperDetailModel&gt;().ForMember(dest =&gt; dest.DisplayId, opt =&gt; opt.MapFrom&lt;DisplayIdResolver, int&gt;(src =&gt; src.DeveloperId));
      }
  }
  </code></pre>
  
  <p>From this one line of code in the AutoMapperProfile constructor I am getting the following compile time error:</p>
  
  <blockquote>
    <p>The type 'WebSite.Utilities.AutoMapper.DisplayIdResolver' cannot be
    used as type parameter 'TValueResolver' in the generic type or method
    'IMemberConfigurationExpression&lt;Developer, DeveloperDetailModel,
    string&gt;.MapFrom&lt;TValueResolver,
    TSourceMember&gt;(Expression&lt;Func&lt;Developer,
    TSourceMember&gt;&gt;)'. There is no implicit reference conversion
    from 'WebSite.Utilities.AutoMapper.DisplayIdResolver' to
    'AutoMapper.IMemberValueResolver&lt;WebSite.Models.DAL.DTO.Developer,
    WebSite.Models.DeveloperDetailModel, int, string&gt;'.</p>
  </blockquote>
  
  <p>From the example shown on the AutoMapper website, it looks as if the Custom Value Resolver <code>Resolve</code> method will only allow the mapping of the two members if they are of the same type. But I've ensured that the type being returned from the resolver method is indeed the type that the destination member is expecting.</p>
  
  <p>It's very likely I am confused by the generics and that I'm making a simple error but I have not been able to figure out what that might be, I've lost all objectivity here.  Is what I'm doing possible or is this not what the resolver was designed for?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Mr Lucian Bargaoanu pointed out that there is an alternate site for AutoMapper documentation at the following <a href="http://docs.automapper.org/en/latest/Value-converters.html" rel="nofollow noreferrer">link</a>. Since this new documentation does not offer an interface example, can I assume that the interface for an <code>IValueConverter</code> is:</p>
  
  <pre><code>public interface IValueConverter&lt;in TSourceMember, TDestinationMember&gt;
  {
      TDestinationMember Resolve(TSourceMember sourceMember, TDestinationMember destinationMember, ResolutionContext context);
  }
  </code></pre>
  
  <p>If that is the case, then this will be of little utility as I do need the source object type in order to map the source members to destination members. I've also just tried using it with an additional object parameter as the source, but the <code>ConvertUsing</code> method does not have an overload that takes 3 arguments. I am not seeing how I can accomplish this with the new documentation either.</p>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>It was suggested that I use IMemberValueResolver. So this is what I did:</p>
  
  <p><code>IMemberValueResolver.cs</code></p>
  
  <pre><code>public interface IMemberValueResolver&lt;in TSource, in TDestination, TSourceMember, TMember&gt;
  {
      TMember Resolve(TSource source, TDestination destination, TSourceMember sourceMember, TMember destinationMember, ResolutionContext context);
  }
  </code></pre>
  
  <p><code>DisplayIdResolver.cs</code></p>
  
  <pre><code>public class DisplayIdResolver : IMemberValueResolver&lt;object, object, int, string&gt;
  {
      public string Resolve(object source, object destination, int sourceMember, string destinationMember, ResolutionContext context)
      {
          if (source.GetType().Equals(typeof(Developer)))
          {
              return IdentifierType.ConvertToDisplayId(sourceMember, IdentifierType.DEVELOPER.Code);
          }
  
          ... more type comparisons here, etc ...
  
          return null;
      }
  }
  </code></pre>
  
  <p><code>AutoMapperProfile.cs</code></p>
  
  <pre><code>public class AutoMapperProfile : Profile
  {
      public AutoMapperProfile()
      {
          CreateMap&lt;Developer, DeveloperDetailModel&gt;().ForMember(dest =&gt; dest.DisplayId, opt =&gt; opt.MapFrom&lt;DisplayIdResolver, int&gt;(src =&gt; src.DeveloperId));
      }
  }
  </code></pre>
  
  <p>Which results in the compile time error:</p>
  
  <blockquote>
    <p>The type 'WebSite.Utilities.AutoMapper.DisplayIdResolver' cannot be
    used as type parameter 'TValueResolver' in the generic type or method
    'IMemberConfigurationExpression&lt;Developer, DeveloperDetailModel,
    string&gt;.MapFrom&lt;TValueResolver,
    TSourceMember&gt;(Expression&lt;Func&lt;Developer,
    TSourceMember&gt;&gt;)'. There is no implicit reference conversion
    from 'WebSite.Utilities.AutoMapper.DisplayIdResolver' to
    'AutoMapper.IMemberValueResolver&lt;WebSite.Models.DAL.DTO.Developer,
    WebSite.Models.DeveloperDetailModel, int, string&gt;'.</p>
  </blockquote>
  
  <p>Which is too bad because I really want to use all the features of AutoMapper. I have followed the example for the simpler case using <code>IValueResolver</code> and that did not work either.  I am using ASP.Net Core 2.2 and the <code>AutoMapper.Extensions.Microsoft.DependencyInjection</code> library for Automapper - as well as a Profile class which i've just included in this example.  I cannot get the simplest case on the AutoMapper website to work nor can I get the more advanced <code>IMemberValueResolver</code> case to work either, following exactly the documentation provided on the website. The website provides an example of the implementation class, but no example of the interface. The MapFrom call in the example does not seem to be correct as no combination of arguments provides me with a syntax that the .NET compiler will accept.</p>
  
  <p>Please note that I am aware that the error states the following:</p>
  
  <blockquote>
    <p>cannot be used as type parameter 'TValueResolver'</p>
  </blockquote>
  
  <p>Yet <strong>as you can clearly see</strong> I am not using the <code>IValueResolver</code> anywhere. I am simply implementing the <code>IMemberValueResolver</code> interface in the class <code>DisplayIdResolver</code> and following the example <em>from the AutoMapper website</em> as to how this will be referred to in the Profile's CreateMap call.</p>
  
  <p><strong>EDIT 3</strong></p>
  
  <p>Using a <a href="https://github.com/AutoMapper/AutoMapper/search?q=IMemberValueResolver&amp;unscoped_q=IMemberValueResolver" rel="nofollow noreferrer">link</a> to the examples on Github I was able to locate the exact test-case scenario that I am trying to accomplish.  However there is no difference between the example on Github and the code I am trying to compile:</p>
  
  <pre><code>    public class CustomResolver : IMemberValueResolver&lt;object, object, int, int&gt;
      {
          public int Resolve(object s, object d, int source, int dest, ResolutionContext context)
          {
              return source + 5;
          }
      }
  
      protected override MapperConfiguration Configuration { get; } = new MapperConfiguration(cfg =&gt;
      {
          cfg.CreateMap&lt;Source, Dest&gt;()
              .ForMember(dto =&gt; dto.SomeValue,
                  opt =&gt; opt.MapFrom&lt;CustomResolver, int&gt;(m =&gt; m.SomeOtherValue));
  
      });
  </code></pre>
  
  <p>As you can see - they are using a generic interface to <code>IMemberValueResolver</code> using the signature  which is what I am doing, except that the return value is a string, not an integer, so it becomes (as I have posted before):</p>
  
  <pre><code>public interface IMemberValueResolver&lt;in TSource, in TDestination, TSourceMember, TMember&gt;
  {
      TMember Resolve(TSource source, TDestination destination, TSourceMember sourceMember, TMember destinationMember, ResolutionContext context);
  }
  </code></pre>
  
  <p>However calling it in the same way they do in the example, results in non-compiling code, as mentioned before (I have posted the stack trace error twice):</p>
  
  <pre><code>CreateMap&lt;Developer, DeveloperDetailModel&gt;().ForMember(dest =&gt; dest.DisplayId, opt =&gt; opt.MapFrom&lt;DisplayIdResolver, int&gt;( src =&gt; src.DeveloperId));
  </code></pre>