如何使用 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)
我该如何解决这个问题?
嗯。我设法使它工作。您必须显式配置从 IAppFile
到 IFormFile
的映射。
所以不是你的配置:
config.ForType<CompanyDto, CompanyMapDto>()
.Map(dest => dest.Logo, src => new AppFileProxy(src.Logo));
使用这个:
TypeAdapterConfig<IFormFile, IAppFile>.ForType() // Or NewConfig()
.MapWith(src => new AppFileProxy(src));
根据我的项目,我需要为“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)
我该如何解决这个问题?
嗯。我设法使它工作。您必须显式配置从 IAppFile
到 IFormFile
的映射。
所以不是你的配置:
config.ForType<CompanyDto, CompanyMapDto>()
.Map(dest => dest.Logo, src => new AppFileProxy(src.Logo));
使用这个:
TypeAdapterConfig<IFormFile, IAppFile>.ForType() // Or NewConfig()
.MapWith(src => new AppFileProxy(src));