• abp学习日志九(总结)


    AutoMaper

    abp支持从Service映射到API,在Service 中有一个CurdAppService的泛型类,泛型类用到了几个参数
    代码如下
    (举例代码)

    /*SystemApp:集合跟(实体)
    *SystemAppDto:查询结果dto
    *Guid:Key
    *PagedAndSortedResultRequestDto:abp给的默认分页排序查询RequestDto
    *CreateSystemAppDto:创建对象的Dto
    *UpdateSystemAppDto:更新对象的Dto
    */
     public class SystemAppService : CrudAppService<SystemApp, SystemAppDto, Guid, PagedAndSortedResultRequestDto, CreateSystemAppDto, UpdateSystemAppDto>, ISystemAppService
        {
            private readonly IRepository<SystemApp, Guid> productRepository;
            private readonly ICurrentTenant currentTenant;
            public SystemAppService(IRepository<SystemApp, Guid> productRepository, ICurrentTenant currentTenant) : base(productRepository)
            {
                this.productRepository = productRepository;
                this.currentTenant = currentTenant;
            }
        }
    

    看到上面的代码有那么多Dto,dto和聚合根(实体)是如何实现属性对应的呢?Abp使用的是AutoMap。
    使用方法就是在项目中(Application项目)有一个XXXXAutoMapperProfile.cs的文件,直接在这里面写上
    CreateMap<SystemApp,SystemAppDto>()
    如果需要更多那就都写上。

    官方文档也是这样说的。

    坑1

    如果你的项目使用的是Module模板,并且是2.2.1以上的版本,请注意,不能使用默认的,除非你的Dto和实体的属性丝毫不差,否则会出现异常。

    • 请添加参数 MemberList.None。关于MemberList枚举类型有三个值,有兴趣可以都试试

    坑2(这个不算坑)

    如果项目存在很多个Dto和实体,那么写Create会写到怀疑人生。可以试试反射,反射的前提是做好namespace,否则反射的方法写起来比较麻烦,我的namespace规则,Dto都在XXXx.Dto命名空间。我的聚合根都在XXX.Model命名空间。

     public VShopApplicationAutoMapperProfile()
            {
                /* You can configure your AutoMapper mapping configuration here.
                 * Alternatively, you can split your mapping configurations
                 * into multiple profile classes for a better organization. */
                var types = Assembly.Load("xxxr.xxx.Application.Contracts").GetTypes();
                var domainTypes = Assembly.Load("xxx.xxx.Domain").GetTypes();
                foreach (var type in types)
                {
                    if (type.Namespace == "xxx.xxx.Dto")
                    {
                        if (type.Name.StartsWith("Create") || type.Name.StartsWith("Update"))
                        {
                            var domainTypeName = type.Name.Replace("Create", "").Replace("Update", "").Replace("Dto", "");
                            if (domainTypes.Any(t => t.Name == domainTypeName))
                                CreateMap(type, domainTypes.First(t => t.Name == domainTypeName), MemberList.None);
                        }
                        else
                        {
                            var domainTypeName = type.Name.Replace("Dto", "");
                            if (domainTypes.Any(t => t.Name == domainTypeName))
                                CreateMap(domainTypes.First(t => t.Name == domainTypeName), type, MemberList.None);
                        }
                    }
                }
            }
    

    Application

    为什么会定位到这个项目呢,因为错误是发生在Service里面的。错误内容如下

    2020-03-29 11:25:38.867 +08:00 [ERR] {
      "code": null,
      "message": "对不起,在处理你的请求期间,产生了一个服务器内部错误!",
      "details": null,
      "validationErrors": null
    }
    2020-03-29 11:25:38.868 +08:00 [ERR] An exception was thrown while activating Castle.Proxies.SystemRoleServiceProxy.
    Autofac.Core.DependencyResolutionException: An exception was thrown while activating Castle.Proxies.SystemRoleServiceProxy.
     ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Castle.Proxies.SystemRoleServiceProxy' can be invoked with the available services and parameters:
    Cannot resolve parameter 'Volo.Abp.Domain.Repositories.IRepository`2[Sugar.VShop.Model.SystemRole,System.Guid] productRepository' of constructor 'Void .ctor(Castle.DynamicProxy.IInterceptor[], Volo.Abp.Domain.Repositories.IRepository`2[Sugar.VShop.Model.SystemRole,System.Guid], Volo.Abp.MultiTenancy.ICurrentTenant)'.
       at Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(IComponentContext context, IEnumerable`1 parameters)
       at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
       at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)
       --- End of inner exception stack trace ---
       at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget)
       at Autofac.Core.Resolving.InstanceLookup.Execute()
       at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
       at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
       at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
       at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
       at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
       at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
       at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
       at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType)
       at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetRequiredService(Type serviceType)
       at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
       at Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext)
       at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
    --- End of stack trace from previous location where exception was thrown ---
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
    

    大致的意思就是无法反射出对应的构造函数。

    网上找到了一个文章很有启发意义 https://www.codetd.com/article/7994226

    这个文章的意思是说没有做DbSet 导致实体无法映射,也就是说聚合根对应的仓储无法反射,这个倒是挺符合道理的。

    但是同样的代码放到 有UI的项目下可用,放到–no-ui的项目下不可用。

    坑1

    填坑。
    需要在EntityFramework项目中添加如下代码

    namespace Sugar.VShop.EntityFrameworkCore
    {
        [DependsOn(
            typeof(VShopDomainModule),
            typeof(AbpEntityFrameworkCoreModule)
        )]
        public class VShopEntityFrameworkCoreModule : AbpModule
        {
            public override void ConfigureServices(ServiceConfigurationContext context)
            {
                context.Services.AddAbpDbContext<VShopDbContext>(options =>
                {
                    //这里是需要添加的代码
                    options.AddDefaultRepositories();
                    /* Add custom repositories here. Example:
                     * options.AddRepository<Question, EfCoreQuestionRepository>();
                     */
                });
            }
    
            public override void OnApplicationInitialization(ApplicationInitializationContext context)
            {
                base.OnApplicationInitialization(context);
            }
        }
    }
    

    因为abp的模板文件就是添加到这里的,但是这个不合理,所以我把这段代码添加到了启动项目下。

    坑2

    不要让Service中包含App或者Application等关键字,比如有个服务叫SystemAppService,映射到API后会没有APP关键字,直接变成了XXX/System/{1}

    https://www.codetd.com/article/7994226

  • 相关阅读:
    锁屏设计文档
    用 jquery 解决 浏览器 兼容问题
    mysql 查询语句
    技术相关
    android Rom 制作2
    android Rom 制作
    UI设计
    jquery 表单验证
    cent os数据库安装
    mysql jdbc 驱动 下载地址官网
  • 原文地址:https://www.cnblogs.com/xiaoch/p/13417910.html
Copyright © 2020-2023  润新知