为什么AutoMapper在将二维数组映射到列表列表时会抛出参数exception

发布于 2025-02-03 19:28:04 字数 8190 浏览 1 评论 0原文

因此,我基本上有一个模型,我想从我的API中返回,但它包含一个矩阵,恰好可以通过文本来实现。 我有这个自动应用程序配置文件,它应该可以解决问题,然后将[,]转向list< list< t>>>

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<Cell, CellDTO>()
            .ForMember(n => n.isBomb, opt => opt.MapFrom(t => t.IsBomb))
            .ForMember(n => n.isRevealed, opt => opt.MapFrom(t => t.IsRevealed))
            .ForMember(n => n.isFlaged, opt => opt.MapFrom(t => t.IsFlagged))
            .ForMember(n => n.bombCount, opt => opt.MapFrom(t => t.BombCount));

        CreateMap<BoardState, BoardStateDTO>()
            .ForMember(n => n.grid, opt => opt.MapFrom(t => _2DMatrixToListList(t.grid)))
            .ForMember(n => n.bombsLeft, opt => opt.MapFrom(t => t.BombsLeft))
            .ForMember(n => n.bombsGenerated, opt => opt.MapFrom(t => t.BombsGenerated));
    }

    private static List<List<T>> _2DMatrixToListList<T>(T[,] array)
    {
        var result = new List<List<T>>();
        var lengthX = array.GetLength(0);
        var lengthY = array.GetLength(1);

        // the reason why we get lengths of dimensions before looping through
        // is because we would like to use `List<T>(int length)` overload
        // this will prevent constant resizing of its underlying array and improve performance
        for (int i = 0; i < lengthX; i++)
        {
            var listToAdd = new List<T>(lengthY);

            for (int i2 = 0; i2 < lengthY; i2++)
            {
                listToAdd.Add(array[i, i2]);
            }

            result.Add(listToAdd);
        }

        return result;
    }
}

但是,每当我调用该方法并尝试使用该方法时config,此错误被抛出:

System.ArgumentException: Argument must be single-dimensional, zero-based array type (Parameter 'array')
   at System.Linq.Expressions.Expression.ArrayLength(Expression array)
   at AutoMapper.Execution.ExpressionBuilder.<ForEach>g__ForEachArrayItem|37_0(ParameterExpression loopVar, Expression array, Expression loopContent)
   at AutoMapper.Execution.ExpressionBuilder.ForEach(ParameterExpression loopVar, Expression collection, Expression loopContent)
   at AutoMapper.Internal.Mappers.CollectionMapper.<MapExpression>g__MapCollectionCore|2_1(Expression destExpression, <>c__DisplayClass2_0& )
   at AutoMapper.Internal.Mappers.CollectionMapper.MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap, MemberMap memberMap, Expression sourceExpression, Expression destExpression)
   at AutoMapper.Execution.ExpressionBuilder.MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap, TypePair typePair, Expression sourceParameter, MemberMap propertyMap, Expression destinationParameter)
   at AutoMapper.Execution.TypeMapPlanBuilder.MapMember(MemberMap memberMap, Expression destinationMemberValue, ParameterExpression resolvedValue)
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateConstructorParameterExpression(ConstructorParameterMap ctorParamMap)
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.ZipIterator[TFirst,TSecond,TResult](IEnumerable`1 first, IEnumerable`1 second, Func`3 resultSelector)+MoveNext()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   at System.Collections.Generic.SparseArrayBuilder`1.ReserveOrAdd(IEnumerable`1 items)
   at System.Linq.Enumerable.Concat2Iterator`1.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
   at System.Linq.Expressions.Expression.Block(IEnumerable`1 variables, IEnumerable`1 expressions)
   at AutoMapper.Execution.TypeMapPlanBuilder.ConstructorMapping(ConstructorMap constructorMap)
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateNewDestinationFunc()
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateDestinationFunc()
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateMapperLambda(HashSet`1 typeMapsPath)
   at AutoMapper.TypeMap.Seal(IGlobalConfiguration configurationProvider, HashSet`1 typeMapsPath)
   at AutoMapper.MapperConfiguration.Seal()
   at AutoMapper.MapperConfiguration..ctor(MapperConfigurationExpression configurationExpression)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.<>c.<AddAutoMapperClasses>b__12_2(IServiceProvider sp)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.<>c.<AddAutoMapperClasses>b__12_3(IServiceProvider sp)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at lambda_method36(Closure , Object , HttpContext )
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass36_0.<Create>b__0(HttpContext httpContext)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

如果有人可以为我澄清这个错误,那就太好了。而且,以下是我使用的模型:

    public struct BoardState
    {
        public Cell[,] grid { get; set; }
        public byte BombsGenerated { get; set; }
        public byte BombsLeft { get; set; }
        public bool isGameOver { get; set; }
        public bool isStarted { get; set; }
    }



public record BoardStateDTO(List<List<CellDTO>> grid, byte bombsGenerated, byte bombsLeft, bool isGameOver, bool isStarted);

So I basically have a model, that I want to return from my API, but it contains a matrix, which happens to be be unserializable by Text.Json, so I'm trying to work around it.
I have this automapper profile, that should do the trick and turn [,] into List<List<T>>:

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<Cell, CellDTO>()
            .ForMember(n => n.isBomb, opt => opt.MapFrom(t => t.IsBomb))
            .ForMember(n => n.isRevealed, opt => opt.MapFrom(t => t.IsRevealed))
            .ForMember(n => n.isFlaged, opt => opt.MapFrom(t => t.IsFlagged))
            .ForMember(n => n.bombCount, opt => opt.MapFrom(t => t.BombCount));

        CreateMap<BoardState, BoardStateDTO>()
            .ForMember(n => n.grid, opt => opt.MapFrom(t => _2DMatrixToListList(t.grid)))
            .ForMember(n => n.bombsLeft, opt => opt.MapFrom(t => t.BombsLeft))
            .ForMember(n => n.bombsGenerated, opt => opt.MapFrom(t => t.BombsGenerated));
    }

    private static List<List<T>> _2DMatrixToListList<T>(T[,] array)
    {
        var result = new List<List<T>>();
        var lengthX = array.GetLength(0);
        var lengthY = array.GetLength(1);

        // the reason why we get lengths of dimensions before looping through
        // is because we would like to use `List<T>(int length)` overload
        // this will prevent constant resizing of its underlying array and improve performance
        for (int i = 0; i < lengthX; i++)
        {
            var listToAdd = new List<T>(lengthY);

            for (int i2 = 0; i2 < lengthY; i2++)
            {
                listToAdd.Add(array[i, i2]);
            }

            result.Add(listToAdd);
        }

        return result;
    }
}

but whenever I call the method and it tries to config, this error is thrown:

System.ArgumentException: Argument must be single-dimensional, zero-based array type (Parameter 'array')
   at System.Linq.Expressions.Expression.ArrayLength(Expression array)
   at AutoMapper.Execution.ExpressionBuilder.<ForEach>g__ForEachArrayItem|37_0(ParameterExpression loopVar, Expression array, Expression loopContent)
   at AutoMapper.Execution.ExpressionBuilder.ForEach(ParameterExpression loopVar, Expression collection, Expression loopContent)
   at AutoMapper.Internal.Mappers.CollectionMapper.<MapExpression>g__MapCollectionCore|2_1(Expression destExpression, <>c__DisplayClass2_0& )
   at AutoMapper.Internal.Mappers.CollectionMapper.MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap, MemberMap memberMap, Expression sourceExpression, Expression destExpression)
   at AutoMapper.Execution.ExpressionBuilder.MapExpression(IGlobalConfiguration configurationProvider, ProfileMap profileMap, TypePair typePair, Expression sourceParameter, MemberMap propertyMap, Expression destinationParameter)
   at AutoMapper.Execution.TypeMapPlanBuilder.MapMember(MemberMap memberMap, Expression destinationMemberValue, ParameterExpression resolvedValue)
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateConstructorParameterExpression(ConstructorParameterMap ctorParamMap)
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.ZipIterator[TFirst,TSecond,TResult](IEnumerable`1 first, IEnumerable`1 second, Func`3 resultSelector)+MoveNext()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   at System.Collections.Generic.SparseArrayBuilder`1.ReserveOrAdd(IEnumerable`1 items)
   at System.Linq.Enumerable.Concat2Iterator`1.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
   at System.Linq.Expressions.Expression.Block(IEnumerable`1 variables, IEnumerable`1 expressions)
   at AutoMapper.Execution.TypeMapPlanBuilder.ConstructorMapping(ConstructorMap constructorMap)
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateNewDestinationFunc()
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateDestinationFunc()
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateMapperLambda(HashSet`1 typeMapsPath)
   at AutoMapper.TypeMap.Seal(IGlobalConfiguration configurationProvider, HashSet`1 typeMapsPath)
   at AutoMapper.MapperConfiguration.Seal()
   at AutoMapper.MapperConfiguration..ctor(MapperConfigurationExpression configurationExpression)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.<>c.<AddAutoMapperClasses>b__12_2(IServiceProvider sp)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.<>c.<AddAutoMapperClasses>b__12_3(IServiceProvider sp)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at lambda_method36(Closure , Object , HttpContext )
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass36_0.<Create>b__0(HttpContext httpContext)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

It would be great if somebody can clarify this one for me. And, here are the models that I use:

    public struct BoardState
    {
        public Cell[,] grid { get; set; }
        public byte BombsGenerated { get; set; }
        public byte BombsLeft { get; set; }
        public bool isGameOver { get; set; }
        public bool isStarted { get; set; }
    }



public record BoardStateDTO(List<List<CellDTO>> grid, byte bombsGenerated, byte bombsLeft, bool isGameOver, bool isStarted);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

肩上的翅膀 2025-02-10 19:28:04

因此,如果有人需要答案,我可以给您。
我的目的是转移[,],所以我需要串行。最后,我只是使用纽顿夫妇来做到这一点。您可以在最新的ASP.NET中手动连接它,如下所示:
到控制器:

builder.Services.AddControllers().AddNewtonsoftJson();

信号枢纽:

 builder.Services.AddSignalR().AddNewtonsoftJsonProtocol();

So, if anybody needs the answer to this, I can kinda give it to you.
My intent was to transfer [,], so I needed to stringify. In the end, I just used Newtonsoft to do this. You can manually connect it in the newest ASP.NET as follows:
To controllers:

builder.Services.AddControllers().AddNewtonsoftJson();

To SignalR hubs:

 builder.Services.AddSignalR().AddNewtonsoftJsonProtocol();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文