如何使用 Mapster 映射到包装器 class?

How can to map to a wrapper class using Mapster?

根据我的项目,我需要为“IFormFile”创建一个包装器,实际上我为此创建了一个“AppFileProxy”class 和“IAppFile”接口:

IAppFile.cs :

public interface IAppFile
{
    string Name { get; }

    string FileName { get; }

    string ContentType { get; }

    long Length { get; }

    void CopyTo(Stream target);
    Task CopyToAsync(Stream target, CancellationToken cancellationToken = default);
    Stream OpenReadStream();
}

AppFileProxy.cs :

public class AppFileProxy : IAppFile
{
    private readonly IFormFile _formFile;

    public AppFileProxy(IFormFile formFile)
    {
        _formFile = formFile ?? throw new ArgumentNullException(nameof(formFile));
    }

    public string Name => _formFile.Name;

    public string FileName => _formFile.FileName;

    public string ContentType => _formFile.ContentType;

    public long Length => _formFile.Length;

    public void CopyTo(Stream target)
    {
        _formFile.CopyTo(target);
    }

    public Task CopyToAsync(Stream target, CancellationToken cancellationToken = default)
    {
        return _formFile.CopyToAsync(target, cancellationToken);
    }

    public Stream OpenReadStream()
    {
        return _formFile.OpenReadStream();
    }
}

现在,我想在动作控制器中使用 Mapster 将“IFormFile”映射到“IAppFile”,如下所示:

CompanyDto.cs :

public class CompanyDto
{
    public string Name { get; set; }
    public IFormFile Logo { get; set; }
}

CompanyMapDto.cs :

public class CompanyMapDto : IRegister
{
    public int Id { get; set; }
    public string Name { get; set; }

    public IAppFile Logo { get; set; }

    public void Register(TypeAdapterConfig config)
    {
        config.ForType<CompanyDto, CompanyMapDto>()
                .Map(dest => dest.Logo, src => new AppFileProxy(src.Logo));
    }
}

动作控制器:

[HttpPost]
[Route("[controller]/[action]")]
public async Task<IActionResult> AddCompanyWithLogo([FromForm]CompanyDto dto)
{
    CompanyMapDto company = dto.Adapt<CompanyMapDto>();

    var stream = company.Logo.OpenReadStream();

    return Ok();
}

但是当我调用操作时,我收到 OpenReadStream() 方法的异常错误:

System.NotImplementedException: The method or operation is not implemented.
   at GeneratedType_1.OpenReadStream()
   at MapsterInDotNet.Controllers.CompaniesController.AddCompanyWithLogo(CompanyDto dto) in C:\Users\Mohsen\source\repos\UseMapsterInDotNet\MapsterInDotNet\MapsterInDotNet\Controllers\CompaniesController.cs:line 52
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我该如何解决这个问题?

嗯。我设法使它工作。您必须显式配置从 IAppFileIFormFile 的映射。

所以不是你的配置:

config.ForType<CompanyDto, CompanyMapDto>()
    .Map(dest => dest.Logo, src => new AppFileProxy(src.Logo));

使用这个:

TypeAdapterConfig<IFormFile, IAppFile>.ForType() // Or NewConfig()
    .MapWith(src => new AppFileProxy(src));