Search code examples
c#asp.netautomapper

AutoMapper custom resolver cannot be used as type parameter


I am trying to create a custom resolver for my AutoMapper that is close to identical to the source documentation for custom resolvers from the AutoMapper team. I have the IValueResolver implementation called NluProgressResolver

public class NluProgressResolver : IValueResolver<CluTrainingJobStateModel, NluTrainingStateDto, object>
{
    public object Resolve(CluTrainingJobStateModel source, NluTrainingStateDto dest, object member, ResolutionContext context)
        => new NluTrainingProgress()
        { 
            Percentage = (source.Result.EvaluationStatus!.PercentComplete + source.Result.TrainingStatus!.PercentComplete) / 2
        };
}

Which takes it's source from CluTrainingJobStateModel and it's destination is NluTrainingStateDto and the targeted destination member is NluTrainingProgress

public class CluTrainingJobStateModel
{
    [JsonPropertyName("result")]
    public required CluTrainingJobStateResult Result { get; set; }
    [JsonPropertyName("jobId")]
    public required string JobId { get; set; }
    [JsonPropertyName("createdDateTime")]
    public string? CreatedDateTime { get; set; }
    [JsonPropertyName("lastUpdatedDateTime")]
    public string? LastUpdatedDateTime { get; set; }
    [JsonPropertyName("expirationDateTime")]
    public string? ExpirationDateTime { get; set; }
    [JsonPropertyName("status")]
    public CluTrainingJobStatus? Status { get; set; }
}
public class NluTrainingStateDto
{
    [JsonPropertyName("id")]
    public required string Id { get; set; }
    [JsonPropertyName("status")]
    public NluTrainingStatus? Status { get; set; }
    [JsonPropertyName("progress")]
    public NluTrainingProgress? Progress { get; set; }
}
public struct NluTrainingProgress
{
    [JsonPropertyName("percentage")]
    public required int Percentage { get; set; }
}

Which I then try to use inside a CreateMap as follows:

CreateMap<CluTrainingJobStateModel, NluTrainingStateDto>()
    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.JobId))
    .ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status))
    .ForMember(dest => dest.Progress, opt => opt.MapFrom<NluProgressResolver>());

This results in an error on the NluProgressResolver as shown below ->

The type 'Namespace.NluProgressResolver' cannot be used as type parameter 'TValueResolver' in the generic type or method 'IMemberConfigurationExpression<CluTrainingJobStateModel, NluTrainingStateDto, NluTrainingProgress?>.MapFrom()'. There is no implicit reference conversion from 'Namespace.NluProgressResolver' to 'AutoMapper.IValueResolver<Namespace.CluTrainingJobStateModel, Namespace.NluTrainingStateDto, Namespace.NluTrainingProgress?>'. (I shortened the actual namespace to `Namespace for to make it easier to read)

I also want to add that I replaced NluTrainingProgress with object in the resolver, but it shows the exact same error but instead referring to object where it says Namespace.NluTrainingProgress?

P.S. I am aware that this is probably not following some best practices, so any tips are welcomed.


Solution

  • This might come off as ironic as it's also a solution I tried before. Changing all the NluTrainingProgress types of the NluProgressResolver class to NluTrainingProgress? resolved my issue, where it didn't before.

    With that I'd like to share the answer to my own question, in case anyone ever runs into this issue.

    
    public class NluProgressResolver : IValueResolver<CluTrainingJobStateModel, NluTrainingStateDto, NluTrainingProgress?>
    {
        public NluTrainingProgress? Resolve(CluTrainingJobStateModel source, NluTrainingStateDto dest, NluTrainingProgress? member, ResolutionContext context)
            => new NluTrainingProgress()
            { 
                Percentage = (source.Result.EvaluationStatus!.PercentComplete + source.Result.TrainingStatus!.PercentComplete) / 2
            };
    }