- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
这是将服务注入类的最常用方法,是将依赖项注入类的首选方式,也是微软推崇的模式。这样,除非提供了所有构造方法注入的依赖项,否则无法构造类,显示的声明了类必需的服务,使开发人员一目了然.
public class BookAppService : ApplicationService
{
private readonly IBookRepository _bookRepository;
public TaxAppService(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
public void DoSomething()
{
//...使用 _bookRepository...
}
}
Microsoft依赖注入库不支持属性注入, 属性注入是Abp框架使用autofac容器替换了微软默认的容器之后才能使用的,属于autofac的特性.
public class BookAppService : ITransientDependency
{
public ILogger<BookAppService> Logger { get; set; }
public BookAppService()
{
Logger = NullLogger<BookAppService>.Instance;
}
public void DoSomething()
{
//...使用 Logger 写日志...
}
}
属性注入依赖项通常被视为可选依赖项.这意味着不是必须的,没有它们服务也可以正常工作.Logger就是这样的依赖项,BookAppService可以继续工作而无需日志记录。为了使依赖项成为可选的,我们通常会为依赖项设置默认值。一般是接口的一个空实现,内部不做任何操作.
属性注入的一个限制是你不能在构造函数中使用依赖项,因为它是在对象构造之后设置的. 。
public class MyService : ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public MyService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void DoSomething()
{
using (var scope = _serviceProvider.CreateScope())
{
var service1 = scope.ServiceProvider.GetService<IMyService1>();
// …
}
}
}
通过 GetService 、 GetRequiredService 可以直接从容器中解析出我们需要的服务,这两个方法有一定的区别,推荐使用 GetRequiredService 方法.
这种情况下一般会使用 using (var scope = _serviceProvider.CreateScope()){} 创建一个域,以便解析出来的服务能够安全的被释放,这也能够减少一些内存消耗.
要注意的一个点是,在以前的ASP.NET Boilerplate 中服务的手动解析使用是通过 IocManager 的,这是静态类,通过 IocManager.Instance 可以获得容器对象,很方便使用。但是在现在的ABP中已经将这种方式移除了,以至于有时候在静态类中需要使用一些服务的时候很不方便(虽然这种方式不是很正确,但是确实有时候会有这样子的需求).
所以在项目中如果真的有需要的话,可以自己构建一个类似于 IocManager 的方式,但是不推荐这样子用,因为在某些情况确实会存在一些问题,导致一些资源和生命周期的冲突,特别是在单元测试之中.
/// <summary>
/// ServiceManager构建一个单例,用于寄放IServiceProvider
/// 使用此类时,需要在应用启动的时候,调用Init方法
/// 一般情况下不推荐使用
/// </summary>
public class ServiceManager
{
private ServiceManager()
{
}
public static IServiceProvider ServiceProvider { get; private set; }
public static void Init(IServiceProvider service)
{
ServiceProvider = service;
}
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
// 保存全局Ioc
if (app != null)
{
ServiceManager.Init(app.ApplicationServices);
}
}
Abp框架中使用autofac依赖注入框架替换了微软默认的容器,在volo.abp.autofac模块中按照模块化设计的思想进行了稍微的封装,提供了便捷的替换方式.
使用autofac替换默认容器的方式:
(1) 在startup类中的ConfigureServices()中,在添加Abp的依赖注入时,通过选项替换.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddApplication<MyWebModule>(options =>
{
//Integrate Autofac!
options.UseAutofac();
});
return services.BuildServiceProviderFromFactory();
}
(2) 在program.cs中,在.net Core 主机(host)创建的时候,调用userAutofac()扩展方法.
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac();
Abp框架使用autofac替换微软默认容器的目的,主要就是为了利用autofac的拦截器功能,这是一种动态aop的实现方式,可以动态的拦截往容器中注册的类,做一些想要的操作。abp框架中的很多横切关注点都是通过这种方式实现的,如权限认证,审计等.
在模块类的 PreConfigureServices() 中,可以使用 OnRegistred() 方法,注册一个回调,每次有类向容器中注册时,都会调用这个回调。在回调中,我们可以对当前注册的类型进行判断(一般通过接口、特性等),如果满足我们的条件,就添加一个拦截器.
在我们调用 useAutofac() 时,内部会调用 UseServiceProviderFactory() 创建了一个 AbpAutofacServiceProviderFactory ,这是实现了微软 IServiceProviderFactory<> 接口的一个容器工厂,任何容器提供了这个接口实现类,并且按照约定提供了 ContainerBuilder ,都可以作为.net core中的依赖注入容器.
在.net Core应用程序启动的时候会调用 IServiceProviderFactory<> 接口的 CreateBuilder(IServiceCollection services) 方法,我们注册的回调函数就是在这个时候执行的。遍历每一个类,在多个回调中进行执行,符合条件的都会添加一个拦截器.
最终是向autofac容器注册拦截器.
拦截器类需要实现 IAbpInterceptor 接口,或者继承 AbpInterceptor ,实现其中的 InterceptAsync 方法。如果对某一个类配置了拦截器,实际上它在注册到容器中时,abp会基于拦截器动态生成一个代理类,再将代理类注册到autofac中.
动态代理是基于Castle实现的。abp继承了Castle动态代理的 AsyncDeterminationInterceptor ,通过继承了 AsyncInterceptorBase 使用适配器模式将拦截器进行包装,并且将方法执行的参数进行封装传递到我们定义的拦截器中.
执行被拦截的类的方法时,实际上通过代理类在执行 InterceptAsync() 方法,这类似于传统过滤器的效果,所以通过这种方式,我们可以在方法执行前后添加一些和业务无关的全局的操作,即一些横切关注点.
ABP 系列总结:
目录: ABP 系列总结 上一篇: ABP - 依赖注入(1) 。
最后此篇关于ABP-依赖注入(2)的文章就讲到这里了,如果你想了解更多关于ABP-依赖注入(2)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我刚刚开始探索 Abp 功能,我从他们的网站创建了一个示例项目并能够成功构建该项目。但是当我运行 dbmigrator 项目时出现异常,下面是错误的截图, 我按照这篇文章运行了应用 https://d
我正在尝试使用 abp.framework(版本 3)为 Entity Framework 数据库播种和 AppUser。我知道如何使用 IdentityUserManager 为 IdentityU
我使用具有商业许可的 abp 套件生成了一个 MVC 项目。它有默认的 Lepton 主题,但我想切换到基本主题,因为它更容易定制。 最佳答案 安装 Volo.Abp.AspNetCore.Mvc.U
我使用具有商业许可的 abp 套件生成了一个 MVC 项目。它有默认的 Lepton 主题,但我想切换到基本主题,因为它更容易定制。 最佳答案 安装 Volo.Abp.AspNetCore.Mvc.U
在我的公司,我们使用全新的 Abp 框架 (abp.io)。由于它是一个新框架,因此缺少很多文档,因此我们必须搜索源代码。看了这么多代码,我意识到这是他们使用的模式,总是出现 Providers、Pr
1. 事件总线 在我们的一个应用中,经常会出现一个逻辑执行之后要跟随执行另一个逻辑的情况,例如一个用户创建了后续还需要发送邮件进行通知,或者需要初始化相应的权限等。面对这样的情况,我们当然可以
ABP框架 ABP是用于创建现代化Web应用程序的完整体系结构和强大的基础架构,以模块化的方式进行开发,所有模块以nuget包的方式提供,开箱即用,遵循最佳实践和约定,提供 SOLID 开
Abp是一个基于模块化开发的应用程序框架,提供了模块化基础的架构和模块化加载的引擎。 理解模块 一个模块是对一个功能点的封装,可以独立成为一个包,实现了松耦合的代码组织方式。A
Abp.NHibernate动态库连接PostgreSQl数据库,供大家参考,具体内容如下 初次接触Abp框架,其框架中封装的操作各类数据的方法还是很好用的,本人还在进一步的学习当中,并将利用ab
在apb-vnext的实体的创建中可以确实字段的长度、说明、对应的表、表中给字段加的索引 以项目中的订单表为例,如下: [Comment("订单主表")] [Tabl
我不能完全理解在什么情况下我会使用 DomainService 和在这种情况下你的文件不详细在这个问题上足够了。你能给出更详细的解释吗举个例子? 如果我只使用 ApplicationService 而
1. 缓存模块源码解析 个人觉得 ABP 分布式缓存模块有三个值得关注的核心点。首先是 AbpRedisCache 类继承了微软原生的 RedisCache,并 通过反射的方式获取RedisC
依赖注入的使用 构造方法注入 这是将服务注入类的最常用方法,是将依赖项注入类的首选方式,也是微软推崇的模式。这样,除非提供了所有构造方法注入的依赖项,否则无法构造类,显示的声明了类必需的服
1. 与 .NET Core 缓存的关系和差异 ABP 框架中的缓存系统核心包是 Volo.Abp.Caching ,而对于分布式缓存的支持,abp 官方提供了基于 Redis 的方案,需要安装
依赖注入实现了系统之间、模块之间和对象之间依赖关系的解耦,基本上是现代应用程序框架必不可少的一个组成部分。 ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microso
默认情况下,AbpUserRole 和AbpRole 实现ISoftDelete。是否可以禁用它? 我试着这样做: [AbpAuthorize(AppPermissions.Pages_Adminis
默认情况下,AbpUserRole 和AbpRole 实现ISoftDelete。是否可以禁用它? 我试着这样做: [AbpAuthorize(AppPermissions.Pages_Adminis
我在构建网站时了解到客户想要 2 个 300x250 的广告和 1 个 728x90 的广告。我已经使用以下 HTML 将这些添加到设计中: 这很好用。我添加
我有一个具有一些可选关系的实体,我正在执行 GetAllIncluding(someProperties),但是当 GetAll 完成时,导航属性保持为 null。 include (Cliente,
为了回应被搁置的问题,我修改了我的问题。希望这能更好地符合 SO 标准。 该程序的目的是构建和发送使用交替位协议(protocol)作为简单重发机制的 UDP 数据包。我已经确认数据包可以正确发送和接
我是一名优秀的程序员,十分优秀!