• 系列教程
  • 开发文档
C# linq如何使用,无法识别方法等问题专场
C# linq如何使用,无法识别方法等问题专场
MySQL常见面试题
MySQL常见面试题
abp+vue-element-admin搭建个人网站
abp+vue-element-admin搭建个人网站
网站SEO优化专题,让搜索引擎对网站更有亲和力
网站SEO优化专题,让搜索引擎对网站更有亲和力
.NET/.NET Core面试题
.NET/.NET Core面试题
.NET Core基于abp vnext 开发个人网站【专题】
.NET Core基于abp vnext 开发个人网站【专题】
vs code 编辑器基础使用专题
vs code 编辑器基础使用专题
  • MySQL JSON_QUOTE() 函数

    MySQLJSON_QUOTE()函数使用双引号包装一个值,使其成为一个JSON字符串值。JSON_QUOTE()语法这里是MySQLJSON_QUOTE()的语法:JSON_QUOTE(str)参数str必需的。一个字符串。返回值JSON_QUOTE()函数返回一个使用双引号包围的JSON字符串值

  • OpenIddict Token格式

  • Abp vNext 番外篇-疑难杂症丨浅谈扩展属性与多用户设计

    系列文章列表,点击展示/隐藏系列教程一目录:知识点源码解析系列教程二目录:BcvpAbpVnext讲解系列教程三目录:单个知识点讲解系列教程四目录:分库分表(日志系统案例讲解)本文梯子正文说明AbpvNext基础篇的文章还差一个单元测试模块就基本上完成了我争取10.1放假之前给大家赶稿出来,后面我们会开始进阶篇,开始拆一些东西,具体要做的事我会单独开一个文章来讲缘起本篇文章缘起于dyAbp大佬们在给夏琳儿(简称:小富婆)讲解技术的时候发起,因为多用户设计和用户扩展属性设计在社区已经是一个每天都会有人来问一遍的问题,这里浅谈一下我的理解,源码是根据EasyAbp作者Super写的代码,根据我自己的理解去分析的想法。扩展属性先从我们单用户系统来讲,如果我该如何扩展用户属性?在Abp默认解决方案Domain.Shared中更改ConpExtraProperties,该操作会向IdentityUser实体添加SocialSecurityNumber属性publicstaticvoidConpExtraProperties(){OneTimeRunner.Run(()=>{ObjectExtensionManager.Instance.Modules().ConpIdentity(identity=>{identity.ConpUser(user=>{user.AddOrUpdateProperty<string>(//propertytype:string"SocialSecurityNumber",//propertynameproperty=>{//validationrulesproperty.Attributes.Add(newRequiredAttribute());property.Attributes.Add(newStringLengthAttribute(64){MinimumLength=4});//...otherconfigurationsforthisproperty});});});});}EntityExtensions还提供了很多配置操作,这里就简单的举几个常用的例子更多详细操作可以在文章下方连接到官方连接。//默认值选项property=>{property.DefaultValue=42;}//默认值工厂选项property=>{property.DefaultValueFactory=()=>DateTime.Now;}//数据注解属性property=>{property.Attributes.Add(newRequiredAttribute());property.Attributes.Add(newStringLengthAttribute(64){MinimumLength=4});}//验证操作property=>{property.Attributes.Add(newRequiredAttribute());property.Attributes.Add(newStringLengthAttribute(64){MinimumLength=4});property.Validators.Add(context=>{if(((string)context.Value).StartsWith("B")){context.ValidationErrors.Add(newValidationResult("Socialsecuritynumbercannotstartwiththeletter'B',sorry!",new[]{"extraProperties.SocialSecurityNumber"}));}});}目前这种配置方式如果你的前端是mvc或者razorpages是不需要改动代码的,页面会动态生成字段,但是如果是angular就需要人工来操作了,除了扩展属性外,你可能还需要部分或完全覆盖某些服务和页面组件才行,不过Abp官方文档都有相应的操作指南所以没有任何问题。具体更多操作官方地址:https://docs.abp.io/en/abp/latest/Module-Entity-Extensions另外就是大家最关系的数据存储问题,默认我们添加的数据都会在ExtraProperties以JSON对象方式进行存储但如果你想用字段的方式进行存储的话,可以在你的.EntityFrameworkCore项目的类中写下这个。然后您需要使用标准Add-Migration和Update-Database命令来创建新的数据库迁移并将更改应用到您的数据库。ObjectExtensionManager.Instance.MapEfCoreProperty<IdentityUser,string>("SocialSecurityNumber",(entityBuilder,propertyBuilder)=>{propertyBuilder.HasMaxLength(64);});多用户设计举例你要开发学生管理系统老师和学生都会进入系统来做自己对应的操作,我们如何来隔离呢?首先我们就可以想到通过角色来做权限分配做能力隔离然后学生和老师的参数不一样,怎么办,老师要填写工号、系部、教学科目、工龄,学生要填写年度、班级、学号?,看到过比较粗暴的方案就是直接在IdentityUser表全给干上去,但是这种做法相对于某个角色来看是不是太冗余?这里我参考Super的一个做法采用使用自己的数据库表/集合创建新实体,具体什么意思呢?我们创建Teacher实体,该实体通过UserId指定IdentityUser,来存储作为老师的额外属性public>Teacher:AggregateRoot<Guid>,IMultiTenant{publicvirtualGuid?TenantId{get;protectedset;}publicvirtualGuidUserId{get;protectedset;}publicvirtualboolActive{get;protectedset;}[NotNull]publicvirtualstringName{get;protectedset;}publicvirtualint?Age{get;protectedset;}protectedTeacher(){}publicTeacher(Guidid,Guid?tenantId,GuiduserId,boolactive,[NotNull]stringname,int?age):base(id){TenantId=tenantId;UserId=userId;Update(active,name,age);}publicvoidUpdate(boolactive,[NotNull]stringname,int?age){Active=active;Name=name;Age=age;}}处理方案是通过订阅UserEto,这是User预定义的专用事件类,当User产生Created、Updated和Deleted操作收会到通知,然后执行我们自己逻辑,[UnitOfWork]public>TeacherUserInfoSynchronizer:IDistributedEventHandler<EntityCreatedEto<UserEto>>,IDistributedEventHandler<EntityUpdatedEto<UserEto>>,IDistributedEventHandler<EntityDeletedEto<UserEto>>,ITransientDependency{privatereadonlyIGuidGenerator_guidGenerator;privatereadonlyICurrentTenant_currentTenant;privatereadonlyIUserRoleFinder_userRoleFinder;privatereadonlyIRepository<Teacher,Guid>_teacherRepository;publicTeacherUserInfoSynchronizer(IGuidGeneratorguidGenerator,ICurrentTenantcurrentTenant,IUserRoleFinderuserRoleFinder,IRepository<Teacher,Guid>teacherRepository){_guidGenerator=guidGenerator;_currentTenant=currentTenant;_userRoleFinder=userRoleFinder;_teacherRepository=teacherRepository;}publicasyncTaskHandleEventAsync(EntityCreatedEto<UserEto>eventData){if(!awaitHasTeacherRoleAsync(eventData.Entity)){return;}awaitCreateOrUpdateTeacherAsync(eventData.Entity,true);}publicasyncTaskHandleEventAsync(EntityUpdatedEto<UserEto>eventData){if(awaitHasTeacherRoleAsync(eventData.Entity)){awaitCreateOrUpdateTeacherAsync(eventData.Entity,true);}else{awaitCreateOrUpdateTeacherAsync(eventData.Entity,false);}}publicasyncTaskHandleEventAsync(EntityDeletedEto<UserEto>eventData){awaitTryUpdateAndDeactivateTeacherAsync(eventData.Entity);}protectedasyncTask<bool>HasTeacherRoleAsync(UserEtouser){varroles=await_userRoleFinder.GetRolesAsync(user.Id);returnroles.Contains(MySchoolConsts.TeacherRoleName);}protectedasyncTaskCreateOrUpdateTeacherAsync(UserEtouser,boolactive){varteacher=awaitFindTeacherAsync(user);if(teacher==null){teacher=newTeacher(_guidGenerator.Create(),_currentTenant.Id,user.Id,active,user.Name,null);await_teacherRepository.InsertAsync(teacher,true);}else{teacher.Update(active,user.Name,teacher.Age);await_teacherRepository.UpdateAsync(teacher,true);}}protectedasyncTaskTryUpdateAndDeactivateTeacherAsync(UserEtouser){varteacher=awaitFindTeacherAsync(user);if(teacher==null){return;}teacher.Update(false,user.Name,teacher.Age);await_teacherRepository.UpdateAsync(teacher,true);}protectedasyncTask<Teacher>FindTeacherAsync(UserEtouser){returnawait_teacherRepository.FindAsync(x=>x.UserId==user.Id);}}结语最后附一下Super大佬的一些教诲:设计思想要结合自己的业务场景,再考虑如何更契合、优雅、易用、可扩展DDD的哲学之一,你不需要,仅仅是你不需要,但是Abp的IdentityManagement模块是需要的不能只看表象不看里层。说过不能模块化还想着模块化,说过看代码就去看数据表,这种先入为主的思维方式才是真正的问题,根本不是技术的原因…不同的领域观察User,它们关心的数据是不一样的,你不关心email,identity模块会关心,所以你冗余出来的MyUser,可以不存储用户email我也是在阅读文档和对照Super大佬的代码后自己的理解,文中可能某些地方可能与作者设计有差距,还请大家多多理解!也欢迎大家阅读我的AbpvNext系列教程联系作者:加群:867095512@MrChuJi

  • MySQL LOG10() 函数

    MySQLLOG10()函数返回指定数字的以10为底的对数。LOG10()语法这里是MySQLLOG10()函数的语法:LOG10(number)LOG10(number)函数等同于LOG(10,number)函数。参数number必需的。一个用于计算对数的数字。该值必须大于0。返回值MySQLLO

  • MySQL SHA1() 函数

    MySQLSHA1()函数计算并返回给定字符串的SHA-1160位校验和。SHA1()函数与MD5()函数类似,也是一种计算摘要的函数。MySQLSHA1()函数等效于SHA()函数。SHA1()语法这里是MySQLSHA1()函数的语法:SHA1(str)参数str必需的。一个要计算SHA-116

  • 青龙面板 企业微信应用推送

    #mermaid-svg-0OOhMjh6Wtew3Yco.label{font-family:'trebuchetms',verdana,arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-0OOhMjh6Wtew3Yco.labeltext{fill:#333}#mermaid-svg-0OOhMjh6Wtew3Yco.noderect,#mermaid-svg-0OOhMjh6Wt

  • MySQL BIT_AND() 函数

    MySQLBIT_AND()函数是一个聚合函数,它对所有的非null输入值执行"按位与"运算。按位与处理两个长度相同的二进制数,两个相应的二进位都为1,该位的结果值才为1,否则为0。BIT_AND()语法这里是MySQLBIT_AND()的语法:BIT_AND(expr)我们通常在SQL中按如下方式

  • OpenIddict Token storage

CSS|HTML   小程序开发   运维部署  开发技巧 推荐阅读

  • MySQL JSON_KEYS() 函数 MySQL JSON_KEYS() 函数 MySQLJSON_KEYS()函数返回一个包含了指定的JSON对象中最上层的成员(key)的数组。JSON_KEYS()语法这里是MySQLJSON_KEYS()的语法:JSON_KEYS(json)JSON_KEYS(json,path)参数json必需的。一个JSON对象文档。path可选的。 文章阅读
  • MySQL 唯一索引 MySQL 唯一索引 我们在设计数据库和表的时候,表中的主键通常为一个自增的数字列。主键列肯定是唯一的。有时候,我们的表中除主键之外的其他列也需要具有唯一值,比如订单表中的订单编号,用户表中的电子邮件和手机号等。我们可以将这些列定义为唯一索引,以保证这些列中不能出现重复值。MySQL唯一索引是一种特殊的索引,它不但可以加 文章阅读
  • MySQL JSON_CONTAINS_PATH() 函数 MySQL JSON_CONTAINS_PATH() 函数 MySQLJSON_CONTAINS_PATH()函数检查一个JSON文档中在指定的路径上是否有值存在。JSON_CONTAINS_PATH()语法这里是MySQLJSON_CONTAINS_PATH()的语法:JSON_CONTAINS_PATH(json,one_or_all,path[,pat 文章阅读

文章|阅读

  • 介绍此系列文章主要是对ABP源码进行解读,初探作者在创造ABP的框架思路,和使用到的设计模式进行。通过解读ABP源码,可以提升ABP使用方式,可以提升编码意识,提高面向对象编程思想。在《ABP源码解析一.ABP启动》中介绍了ABP是如何启动的。此篇文章主要解读ABP框架中IOC相关内容介绍。ABP中的Ioc容器依赖CastleWindsor。在ABP启动中,可以看到是如何使用IOC的,在AbpBootstrapper构造函数中,有如下代码//设置Ioc管理器IocManager=options.IocManager;由此可知,ABP容器是通过options传递到启动类中的,通过阅读AbpBootstrapperOptions类publicAbpBootstrapperOptions(){IocManager=Abp.Dependency.IocManager.Instance;PlugInSources=newPlugInSourceList();}得知选项中的IocManager是Abp.Dependency.IocManager.Instance所得。接下来我们主要依据IocManager.Instance进行代码分析。类文件结构图IocManagerIIocManagerIIocRegistrarIIocResolverIConventionalRegistrationContextIConventionalDependencyRegistrarConventionalRegistrationConfigDependencyLifeStyle源码解析主要接口abp和ioc有关的接口主要有三个IIocRegistrar:用于注册依赖项的类的接口IIocResolver:用于解析依赖的类的接口IIocManager:用于注册和解析依赖项的接口1.IIocRegistrarIIocRegistrar主要提供了各种注册依赖项的方法,以及提供是否已注册的检测方法主要有:普通注册:AddConventionalRegistrar程序集注册:RegisterAssemblyByConvention类型注册:Register检查是否已注册:IsRegistered///<summary>///Defineinterfacefor>///定义用于注册依赖项的类的接口///</summary>publicinterfaceIIocRegistrar{///<summary>///Addsadependencyregistrarforconventionalregistration.///添加依赖注册器///</summary>///<paramname="registrar">dependencyregistrar</param>voidAddConventionalRegistrar(IConventionalDependencyRegistrarregistrar);///<summary>///Registerstypesofgivenassemblybyallconventionalregistrars.See<seecref="IocManager.AddConventionalRegistrar"/>method.///注册指定的信息集///</summary>///<paramname="assembly">Assemblytoregister</param>voidRegisterAssemblyByConvention(Assemblyassembly);///<summary>///Registerstypesofgivenassemblybyallconventionalregistrars.See<seecref="IocManager.AddConventionalRegistrar"/>method.///注册指定的信息集///</summary>///<paramname="assembly">Assemblytoregister///指定的信息集///</param>///<paramname="config">Additionalconfiguration///配置///</param>voidRegisterAssemblyByConvention(Assemblyassembly,ConventionalRegistrationConfigconfig);///<summary>///Registersatypeasselfregistration.///注册自身类型///</summary>///<typeparamname="T">Typeofthe>///类的类型///</typeparam>///<paramname="lifeStyle">Life>DependencyLifeStyle.Singleton)whereT:>;///<summary>///Registersatypeasselfregistration.///注册自身类型///</summary>///<paramname="type">Typeofthe>///类的类型///</param>///<paramname="lifeStyle">Life>DependencyLifeStyle.Singleton);///<summary>///Registersatypewithit'simplementation.///注册一个类型的实现///</summary>///<typeparamname="TType">Registeringtype///注册类型///</typeparam>///<typeparamname="TImpl">Thetypethatimplements<seecref="TType"/>///实现类型///</typeparam>///<paramname="lifeStyle">Life>DependencyLifeStyle.Singleton)whereTType:>whereTImpl:>,TType;///<summary>///Registersatypewithit'simplementation.///注册一个类型的实现///</summary>///<paramname="type">Typeofthe>///注册类型///</param>///<paramname="impl">Thetypethatimplements///实现类型///<paramrefname="type"/></param>///<paramname="lifeStyle">Life>DependencyLifeStyle.Singleton);///<summary>///Checkswhethergiventypeisregisteredbefore.///检查指定类型是否已注册///</summary>///<paramname="type">Typetocheck///指定类型///</param>boolIsRegistered(Typetype);///<summary>///Checkswhethergiventypeisregisteredbefore.///检查指定类型是否已注册///</summary>///<typeparamname="TType">Typetocheck///指定类型///</typeparam>boolIsRegistered<TType>();}2.IIocResolverIIocResolver接口主要提供了如何从ioc容器中解析组件的方法,主要有解析单个组件:Resolve解析全部组件:ResolveAll检查组件是否已注册:IsRegistered///<summary>///Defineinterfacefor>///定义用于解析依赖的类的接口///</summary>publicinterfaceIIocResolver{///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取一个对象///</summary>///<typeparamname="T">Typeoftheobjecttoget///获取类型///</typeparam>///<returns>Theobjectinstance///对象实例///</returns>TResolve<T>();///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取一个对象///</summary>///<typeparamname="T">Typeoftheobjecttocast///对象转到的类型///</typeparam>///<paramname="type">Typeoftheobjecttoresolve///解析的对象类型///</param>///<returns>Theobjectinstance///对象实例///</returns>TResolve<T>(Typetype);///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取一个对象///</summary>///<typeparamname="T">Typeoftheobjecttoget///获取的对象类型///</typeparam>///<paramname="argumentsAsAnonymousType">Constructorarguments///构造函数参数///</param>///<returns>Theobjectinstance///对象实例///</returns>TResolve<T>(objectargumentsAsAnonymousType);///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取一个对象///</summary>///<paramname="type">Typeoftheobjecttoget///获取对象的类型///</param>///<returns>Theobjectinstance///对象实例///</returns>objectResolve(Typetype);///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取一个对象///</summary>///<paramname="type">Typeoftheobjecttoget///获取对象的类型///</param>///<paramname="argumentsAsAnonymousType">Constructorarguments///构造函数参数///</param>///<returns>Theobjectinstance///对象实例///</returns>objectResolve(Typetype,objectargumentsAsAnonymousType);///<summary>///Getsallimplementationsforgiventype.///ReturningobjectsmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取全部对象///</summary>///<typeparamname="T">Typeoftheobjectstoresolve///解析对象的类型///</typeparam>///<returns>Objectinstances///全部对象实例///</returns>T[]ResolveAll<T>();///<summary>///Getsallimplementationsforgiventype.///ReturningobjectsmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取全部对象///</summary>///<typeparamname="T">Typeoftheobjectstoresolve///解析对象的类型///</typeparam>///<paramname="argumentsAsAnonymousType">Constructorarguments///构造函数参数///</param>///<returns>Objectinstances///全部对象实例///</returns>T[]ResolveAll<T>(objectargumentsAsAnonymousType);///<summary>///Getsallimplementationsforgiventype.///ReturningobjectsmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取指定类型的全部对象///</summary>///<paramname="type">Typeoftheobjectstoresolve///解析对象的类型///</param>///<returns>Objectinstances///全部对象实例///</returns>object[]ResolveAll(Typetype);///<summary>///Getsallimplementationsforgiventype.///ReturningobjectsmustbeReleased(see<seecref="Release"/>)afterusage.///从IOC容器中获取指定类型的全部对象///</summary>///<paramname="type">Typeoftheobjectstoresolve///解析对象的类型///</param>///<paramname="argumentsAsAnonymousType">Constructorarguments///构造函数参数///</param>///<returns>Objectinstances///全部对象实例///</returns>object[]ResolveAll(Typetype,objectargumentsAsAnonymousType);///<summary>///Releasesapre-resolvedobject.SeeResolvemethods.///释放解析对象///</summary>///<paramname="obj">Objecttobereleased///被释放的对象///</param>voidRelease(objectobj);///<summary>///Checkswhethergiventypeisregisteredbefore.///检查给定类型是否已注册///</summary>///<paramname="type">Typetocheck///指定类型///</param>boolIsRegistered(Typetype);///<summary>///Checkswhethergiventypeisregisteredbefore.///检查给定类型是否已注册///</summary>///<typeparamname="T">Typetocheck///指定类型///</typeparam>boolIsRegistered<T>();}3.IIocManagerIIocManager继承自:IIocRegistrar,IIocResolver,提供Ioc容器访问属性///<summary>///Thisinterfaceisusedtodirectlyperformdependencyinjectiontasks.///用于注册和解析依赖项的接口///</summary>publicinterfaceIIocManager:IIocRegistrar,IIocResolver,IDisposable{///<summary>///ReferencetotheCastleWindsorContainer.///Ioc容器///</summary>IWindsorContainerIocContainer{get;}///<summary>///Checkswhethergiventypeisregisteredbefore.///检查指定类型是否已经注入///</summary>///<paramname="type">Typetocheck///检查的类型///</param>newboolIsRegistered(Typetype);///<summary>///Checkswhethergiventypeisregisteredbefore.///检查指定类型是否已经注入///</summary>///<typeparamname="T">Typetocheck///检查的类型///</typeparam>newboolIsRegistered<T>();}IocManager实现IocManager是主要实现类,在此类中,初始化Windsor容器,编译能够将类型注入到ioc容器中和从ioc容器中解析组件。///<summary>///This>///负责依赖注入///</summary>public>IocManager:IIocManager{///<summary>///TheSingletoninstance.///IocManager单例///</summary>publicstaticIocManagerInstance{get;privateset;}///<summary>///ReferencetotheCastleWindsorContainer.///CastleWindsor容器///</summary>publicIWindsorContainerIocContainer{get;privateset;}///<summary>///Listofallregisteredconventionalregistrars.///</summary>privatereadonlyList<IConventionalDependencyRegistrar>_conventionalRegistrars;staticIocManager(){Instance=newIocManager();}///<summary>///Createsanew<seecref="IocManager"/>object.///Normally,youdon'tdirectlyinstantiatean<seecref="IocManager"/>.///Thismaybeusefulfortestpurposes.///</summary>publicIocManager(){IocContainer=newWindsorContainer();_conventionalRegistrars=newList<IConventionalDependencyRegistrar>();//Registerself!IocContainer.Register(Component.For<IocManager,IIocManager,IIocRegistrar,IIocResolver>().UsingFactoryMethod(()=>this));}///<summary>///Addsadependencyregistrarforconventionalregistration.///</summary>///<paramname="registrar">dependencyregistrar</param>publicvoidAddConventionalRegistrar(IConventionalDependencyRegistrarregistrar){_conventionalRegistrars.Add(registrar);}///<summary>///Registerstypesofgivenassemblybyallconventionalregistrars.See<seecref="AddConventionalRegistrar"/>method.///</summary>///<paramname="assembly">Assemblytoregister</param>publicvoidRegisterAssemblyByConvention(Assemblyassembly){RegisterAssemblyByConvention(assembly,newConventionalRegistrationConfig());}///<summary>///Registerstypesofgivenassemblybyallconventionalregistrars.See<seecref="AddConventionalRegistrar"/>method.///</summary>///<paramname="assembly">Assemblytoregister</param>///<paramname="config">Additionalconfiguration</param>publicvoidRegisterAssemblyByConvention(Assemblyassembly,ConventionalRegistrationConfigconfig){varcontext=newConventionalRegistrationContext(assembly,this,config);foreach(varregistererin_conventionalRegistrars){registerer.RegisterAssembly(context);}if(config.InstallInstallers){IocContainer.Install(FromAssembly.Instance(assembly));}}///<summary>///Registersatypeasselfregistration.///</summary>///<typeparamname="TType">Typeofthe>Life>{IocContainer.Register(ApplyLife>Typeofthe>Life>{IocContainer.Register(ApplyLife>Registeringtype</typeparam>///<typeparamname="TImpl">Thetypethatimplements<seecref="TType"/></typeparam>///<paramname="lifeStyle">Life>{IocContainer.Register(ApplyLife>Typeofthe>Thetypethatimplements<paramrefname="type"/></param>///<paramname="lifeStyle">Life>{IocContainer.Register(ApplyLife>Typetocheck</param>publicboolIsRegistered(Typetype){returnIocContainer.Kernel.HasComponent(type);}///<summary>///Checkswhethergiventypeisregisteredbefore.///</summary>///<typeparamname="TType">Typetocheck</typeparam>publicboolIsRegistered<TType>(){returnIocContainer.Kernel.HasComponent(typeof(TType));}///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="IIocResolver.Release"/>)afterusage.///</summary>///<typeparamname="T">Typeoftheobjecttoget</typeparam>///<returns>Theinstanceobject</returns>publicTResolve<T>(){returnIocContainer.Resolve<T>();}///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="Release"/>)afterusage.///</summary>///<typeparamname="T">Typeoftheobjecttocast</typeparam>///<paramname="type">Typeoftheobjecttoresolve</param>///<returns>Theobjectinstance</returns>publicTResolve<T>(Typetype){return(T)IocContainer.Resolve(type);}///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="IIocResolver.Release"/>)afterusage.///</summary>///<typeparamname="T">Typeoftheobjecttoget</typeparam>///<paramname="argumentsAsAnonymousType">Constructorarguments</param>///<returns>Theinstanceobject</returns>publicTResolve<T>(objectargumentsAsAnonymousType){returnIocContainer.Resolve<T>(argumentsAsAnonymousType);}///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="IIocResolver.Release"/>)afterusage.///</summary>///<paramname="type">Typeoftheobjecttoget</param>///<returns>Theinstanceobject</returns>publicobjectResolve(Typetype){returnIocContainer.Resolve(type);}///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="IIocResolver.Release"/>)afterusage.///</summary>///<paramname="type">Typeoftheobjecttoget</param>///<paramname="argumentsAsAnonymousType">Constructorarguments</param>///<returns>Theinstanceobject</returns>publicobjectResolve(Typetype,objectargumentsAsAnonymousType){returnIocContainer.Resolve(type,argumentsAsAnonymousType);}///<inheritdoc/>publicT[]ResolveAll<T>(){returnIocContainer.ResolveAll<T>();}///<inheritdoc/>publicT[]ResolveAll<T>(objectargumentsAsAnonymousType){returnIocContainer.ResolveAll<T>(argumentsAsAnonymousType);}///<inheritdoc/>publicobject[]ResolveAll(Typetype){returnIocContainer.ResolveAll(type).Cast<object>().ToArray();}///<inheritdoc/>publicobject[]ResolveAll(Typetype,objectargumentsAsAnonymousType){returnIocContainer.ResolveAll(type,argumentsAsAnonymousType).Cast<object>().ToArray();}///<summary>///Releasesapre-resolvedobject.SeeResolvemethods.///</summary>///<paramname="obj">Objecttobereleased</param>publicvoidRelease(objectobj){IocContainer.Release(obj);}///<inheritdoc/>publicvoidDispose(){IocContainer.Dispose();}privatestaticComponentRegistration<T>ApplyLife>1.初始化容器在IocManager构造函数,初始化了WindsorContainer容器,并且将自身实例,注入到容器中,以便能解析IocManager,IIocManager,IIocRegistrar,IIocResolver组件publicIocManager(){IocContainer=newWindsorContainer();_conventionalRegistrars=newList<IConventionalDependencyRegistrar>();//Registerself!IocContainer.Register(Component.For<IocManager,IIocManager,IIocRegistrar,IIocResolver>().UsingFactoryMethod(()=>this));}2.注册组件由于已经初始化了WindsorContainer容器,abp抽象了集中常用的注册方式,直接注入到容器中publicvoidRegisterAssemblyByConvention(Assemblyassembly,ConventionalRegistrationConfigconfig){varcontext=newConventionalRegistrationContext(assembly,this,config);foreach(varregistererin_conventionalRegistrars){registerer.RegisterAssembly(context);}if(config.InstallInstallers){IocContainer.Install(FromAssembly.Instance(assembly));}}publicvoidRegister<TType>(DependencyLifeStylelifeStyle=DependencyLifeStyle.Singleton)whereTType:>{IocContainer.Register(ApplyLife>3.解析组件抽象方法,从WindsorContainer中解析///<summary>///GetsanobjectfromIOCcontainer.///ReturningobjectmustbeReleased(see<seecref="IIocResolver.Release"/>)afterusage.///</summary>///<typeparamname="T">Typeoftheobjecttoget</typeparam>///<returns>Theinstanceobject</returns>publicTResolve<T>(){returnIocContainer.Resolve<T>();}///<inheritdoc/>publicT[]ResolveAll<T>(){returnIocContainer.ResolveAll<T>();}4.检查是否已注册检测组件是否已在WindsorContainer中注册///<summary>///Checkswhethergiventypeisregisteredbefore.///</summary>///<paramname="type">Typetocheck</param>publicboolIsRegistered(Typetype){returnIocContainer.Kernel.HasComponent(type);}///<summary>///Checkswhethergiventypeisregisteredbefore.///</summary>///<typeparamname="TType">Typetocheck</typeparam>publicboolIsRegistered<TType>(){returnIocContainer.Kernel.HasComponent(typeof(TType));}设计模式1.单例模式IocManager提供的单例模式,严格意义上,IocManager类还不算是单例,因为其构造方法是public,也就意味着,可以直接创建IocManager实例。///<summary>///TheSingletoninstance.///IocManager单例///</summary>publicstaticIocManagerInstance{get;privateset;}staticIocManager(){Instance=newIocManager();}publicIocManager(){}2.代理模式IocManager也使用到了代理模式,抽象封装自己的接口信息,代理IWindsorContainer,丰富框架内的接口。测试代码和ioc容器有关的测试,如下图ioc测试public>IocManager_LifeStyle_Tests:TestBaseWithLocalIocManager{///<summary>///当组件释放时需要调用Dispose///</summary>[Fact]publicvoidShould_Call_Dispose_Of_Transient_Dependency_When_Object_Is_Released(){LocalIocManager.IocContainer.Register(Component.For<SimpleDisposableObject>().Life>LocalIocManager.IocContainer.Resolve<SimpleDisposableObject>();LocalIocManager.IocContainer.Release(obj);obj.DisposeCount.ShouldBe(1);}///<summary>///当iocManager释放之后,对象也被释放///</summary>[Fact]publicvoidShould_Call_Dispose_Of_Transient_Dependency_When_IocManager_Is_Disposed(){LocalIocManager.IocContainer.Register(Component.For<SimpleDisposableObject>().Life>LocalIocManager.IocContainer.Resolve<SimpleDisposableObject>();LocalIocManager.Dispose();obj.DisposeCount.ShouldBe(1);}///<summary>///当iocManager释放之后,单例对象也被释放///</summary>[Fact]publicvoidShould_Call_Dispose_Of_Singleton_Dependency_When_IocManager_Is_Disposed(){LocalIocManager.IocContainer.Register(Component.For<SimpleDisposableObject>().Life>LocalIocManager.IocContainer.Resolve<SimpleDisposableObject>();LocalIocManager.Dispose();obj.DisposeCount.ShouldBe(1);}}public>ScopedIocResolver_Tests:TestBaseWithLocalIocManager{///<summary>///scope需要正常运行///</summary>[Fact]publicvoidUsingScope_Test_ShouldWork(){LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);SimpleDisposableObjectsimpleObj=null;LocalIocManager.UsingScope(scope=>{simpleObj=scope.Resolve<SimpleDisposableObject>();});simpleObj.DisposeCount.ShouldBe(1);}///<summary>///带有构造函数的scope能够正常运行///</summary>[Fact]publicvoidUsingScope_Test_With_Constructor_ShouldWork(){LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);SimpleDisposableObjectsimpleObj=null;LocalIocManager.UsingScope(scope=>{simpleObj=scope.Resolve<SimpleDisposableObject>(new{myData=40});});simpleObj.MyData.ShouldBe(40);}///<summary>///IIocScopedResolver接口正常///</summary>[Fact]publicvoidIIocScopedResolver_Test_ShouldWork(){LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);LocalIocManager.Register<SimpleDisposableObject2>(DependencyLifeStyle.Transient);LocalIocManager.Register<SimpleDisposableObject3>(DependencyLifeStyle.Transient);SimpleDisposableObjectsimpleObj;SimpleDisposableObject2simpleObj2;SimpleDisposableObject3simpleObj3;using(varscope=LocalIocManager.CreateScope()){simpleObj=scope.Resolve<SimpleDisposableObject>();simpleObj2=scope.Resolve<SimpleDisposableObject2>();simpleObj3=scope.Resolve<SimpleDisposableObject3>();}simpleObj.DisposeCount.ShouldBe(1);simpleObj2.DisposeCount.ShouldBe(1);simpleObj3.DisposeCount.ShouldBe(1);}///<summary>///IIocScopedResolver接口正常,解析组件有构造函数///</summary>[Fact]publicvoidIIocScopedResolver_Test_With_ConstructorArgs_ShouldWork(){LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);LocalIocManager.Register<SimpleDisposableObject2>(DependencyLifeStyle.Transient);LocalIocManager.Register<SimpleDisposableObject3>(DependencyLifeStyle.Transient);SimpleDisposableObjectsimpleObj;SimpleDisposableObject2simpleObj2;SimpleDisposableObject3simpleObj3;using(varscope=LocalIocManager.CreateScope()){simpleObj=scope.Resolve<SimpleDisposableObject>(new{myData=40});simpleObj2=scope.Resolve<SimpleDisposableObject2>(new{myData=4040});simpleObj3=scope.Resolve<SimpleDisposableObject3>(new{myData=404040});}simpleObj.MyData.ShouldBe(40);simpleObj2.MyData.ShouldBe(4040);simpleObj3.MyData.ShouldBe(404040);}[Fact]publicvoidIIocScopedResolver_Test_ResolveAll_Should_DisposeAll_Registrants(){LocalIocManager.Register<ISimpleDependency,SimpleDependency>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency2>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency3>(DependencyLifeStyle.Transient);IEnumerable<ISimpleDependency>simpleDependendcies;using(varscope=LocalIocManager.CreateScope()){simpleDependendcies=scope.ResolveAll<ISimpleDependency>();}simpleDependendcies.ShouldAllBe(d=>d.DisposeCount==1);}[Fact]publicvoidIIocScopedResolver_Test_ResolveAll_Should_Work_WithConstructor(){LocalIocManager.Register<ISimpleDependency,SimpleDependency>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency2>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency3>(DependencyLifeStyle.Transient);IEnumerable<ISimpleDependency>simpleDependendcies;using(varscope=LocalIocManager.CreateScope()){simpleDependendcies=scope.ResolveAll<ISimpleDependency>(new{myData=40});}simpleDependendcies.ShouldAllBe(x=>x.MyData==40);}[Fact]publicvoidIIocScopedResolver_Test_ResolveAll_Should_Work_With_OtherResolvings(){LocalIocManager.Register<ISimpleDependency,SimpleDependency>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency2>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency3>(DependencyLifeStyle.Transient);LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);IEnumerable<ISimpleDependency>simpleDependendcies;SimpleDisposableObjectsimpleObject;using(varscope=LocalIocManager.CreateScope()){simpleDependendcies=scope.ResolveAll<ISimpleDependency>();simpleObject=scope.Resolve<SimpleDisposableObject>();}simpleDependendcies.ShouldAllBe(x=>x.DisposeCount==1);simpleObject.DisposeCount.ShouldBe(1);}[Fact]publicvoidIIocScopedResolver_Test_ResolveAll_Should_Work_With_OtherResolvings_ConstructorArguments(){LocalIocManager.Register<ISimpleDependency,SimpleDependency>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency2>(DependencyLifeStyle.Transient);LocalIocManager.Register<ISimpleDependency,SimpleDependency3>(DependencyLifeStyle.Transient);LocalIocManager.Register<SimpleDisposableObject>(DependencyLifeStyle.Transient);IEnumerable<ISimpleDependency>simpleDependendcies;SimpleDisposableObjectsimpleObject;using(varscope=LocalIocManager.CreateScope()){simpleDependendcies=scope.ResolveAll<ISimpleDependency>(new{myData=40});simpleObject=scope.Resolve<SimpleDisposableObject>(new{myData=40});}simpleDependendcies.ShouldAllBe(x=>x.MyData==40);simpleObject.MyData.ShouldBe(40);}[Fact]publicvoidIIocScopedResolver_Test_IsRegistered_ShouldWork(){LocalIocManager.Register<ISimpleDependency,SimpleDependency>(DependencyLifeStyle.Transient);using(varscope=LocalIocManager.CreateScope()){scope.IsRegistered<ISimpleDependency>().ShouldBe(true);scope.IsRegistered(typeof(ISimpleDependency)).ShouldBe(true);}}[Fact]publicvoidIIocScopedResolver_Test_Custom_Release_ShouldWork(){LocalIocManager.Register<ISimpleDependency,SimpleDependency>(DependencyLifeStyle.Transient);ISimpleDependencysimpleDependency;using(varscope=LocalIocManager.CreateScope()){simpleDependency=scope.Resolve<ISimpleDependency>();scope.Release(simpleDependency);}simpleDependency.DisposeCount.ShouldBe(1);}}publicinterfaceISimpleDependency:IDisposable{intMyData{get;set;}intDisposeCount{get;set;}}public>SimpleDependency:ISimpleDependency{publicintMyData{get;set;}publicintDisposeCount{get;set;}publicvoidDispose(){DisposeCount++;}}public>SimpleDependency2:ISimpleDependency{publicintDisposeCount{get;set;}publicintMyData{get;set;}publicvoidDispose(){DisposeCount++;}}public>SimpleDependency3:ISimpleDependency{publicintMyData{get;set;}publicintDisposeCount{get;set;}publicvoidDispose(){DisposeCount++;}}运行测试结果我的公众

    .Net

  • 千万级别的表分页查询非常慢,如何改进?

    在实际的软件系统开发过程中,随着使用的用户群体越来越多,表数据也会随着时间的推移,单表的数据量会越来越大。以订单表为例,假如每天的订单量在 4 万左右,那么一个月的订单量就是 120 多万,一年就是 1400 多万,随着年数的增加和单日下单量的增加,订单表的数据量会越来越庞大,订单数据的查询不会像最初那样简单快速,如果查询关键字段没有走索引,会直接影响到用户体验,甚至会影响到服务是否能正常运行!

    Database

  • 首先贴代码将几个需要注意的点:1、当获取不到微信小程序APPID和微信小程序APPSECRET时只能在微信浏览器打开小程序2、此代码只要是在微信环境打开小程序3、需要在线上域名调试,本地看不到效果,可将本地host反向代理到线上域名进行调试4、wx-open-launch-weapp标签内样式只支持px,要自适应需再将rpx转px5、需要服务端的接口生成签名和公众号的一些数据给前端6、前端安装模块npminstalljweixin-module--save7、main.js添加一行代

    小程序

  • 小程序云开发请求云函数成功,但result为空/null的处理,四种问题处理方法汇总

    小程序云开发请求云函数成功,但result为空的处理方法大家在测试微信小程序的时候,很多情况会遇到返回为空的状态1.第一种问题方法Promise云函数返回的数据使用方法会返回一个Promise,所以需要写Promise格式才能获取wx.cloud.callFunction({name:'delQuesById',//需调用的云函数名,注意名称要相同//传给云函数的参数也就是上边的event对象data:{

    小程序

  • 2021目标期望没达到预期,今天过后所有的期待与努力无最爱、无例外、往事清零,一起跨入2022,续上昨日的期

    Life

2024年 04月26日

周五