第三节 通过Autofac中间件实现注册依赖

在开发中使用Autofac、MEF中间件的根本目地是在整个的程序开发中,从前台的可视界面到最终的数据提交到数据库中这一流程可以被执行并通过,从纵向上保证了整个应用程序开发的可行性,而程序的其它功能和实现只是在此基础上横向的添加或扩展。相对于常规的从数据库到前台可视界面的常规开发,它特别适用于一个全新程序工程的开发,而对于一个已经存在程序工程的重构或修改,虽然依然可以使用Autofac、MEF中间件,但是其开发中所关注的重点已经从可行性变为了对代码、方法、调用逻辑和功能的重构或修改上来了。它们的另一个重要功能是调用类的接口而不直接调用类的下定义如:new 对象名。

Autofac、MEF中间件两者都是通过注册依赖而实现在整个程序开发过程的依赖倒置。在实现开发中我发现相对来说MEF的定义、实现和使用相对来说比较傻瓜和容易,Autofac的功能比较强大,但是两者整体性能的好坏本人了解较少不做评论。

nopCommerce_4.10应用程序通过Autofac中间件实现依赖注册,它第一步所做的,首先是查找到与程序集相对应用的处于~\Web\bin\Debug\netcoreapp2.1文件夹中的dll文件实现查找查找程序集与dll文件功能和方法定义在Core项目中的ItypeFinder接口、WebAppTypeFinder类和AppDomainTypeFinder类中,而INopFileProvider接口、NopFileProvider类、NopException类、CommonHelper类则是为上述三者提供所要实现功能中的方法提供支撑。类BaseSingleton 和Singleton则是在保证在网络环境中运行nopCommerce_4.10应用程序时,如果一个实例被一个用户调用后,在其数据被提交的数据库中前,在期间这个实例将不能被其他用户调用而被创建(上述这些类在第二节中已经被定义或实现,在此对其功能做一些详细的说明)。

一、定义注册

  1. 定义Core.Infrastructure.DependencyManagement.IdependencyRegistrar接口,它调用了该接口所在项目中Configuration文件夹中的NopConfig类。实际上在反向开发过程中发现定义的Configuration文件夹中的所有的类或接口它们都是支撑资源,它们只被其它的类或方法所调用。

  2. 定义Framework.Infrastructure.DependencyRegistrar类(注意:该类的定义也许要对Autofac进行引用,我们并未在此项目的NuGet的引用中找到对Autofac进行引用,但是在其引用的Core项目中存在对Autofac引用,这是间接引用在nopCommerce_4.10应用程序中的第二次体现)。在该类的Register方法中定义了许多的类及其接口的注册,但是在最简的实现中其它的都可以被注释掉或删除,有用的只有下列三句:

builder.RegisterType<SettingService>().As<ISettingService>().InstancePerLifetimeScope();

    //register all settings

builder.RegisterSource(new SettingsSource());

3、因为在方法Register调用了SettingService类及其接口所以要在程序中新建一个Service项目,并定义了SettingService类及其接口,同时被引用到Framework项目中,最终效果见图1-4

图1-4

4、SettingService类及其接口需要Core.Domain.Configuration.SettingCore.Domain.Localization. IlocalizedEntity接口和Core.BaseEntity类作为支撑。所有需要在Core项目中定义上述对象(它们之间的详细调用逻辑见源代码中的002_通过Autofac实现注册依赖.vsdx文件)。同时Core项目引用到Service项目中。

nopCommerce_4.10应用程序中的SettingService类中下定义的许多的方法及其拷贝构造方法。但是为了使用调用逻辑更加简洁、清晰,对于最简实现的来说LoadSetting和GetSettingBy两个方法是当前必须被定义的。其它都可以被注释或删除掉(包括其拷贝构造方法)。在反向开发的过程中会发现,nopCommerce_4.10应用程序实际上是通过对Setting实体的操作把前台界面中的数据到持久化到相应的数据库存中的表中,这一点说明, Setting实体及其操作是整个nopCommerce_4.10应用程序纵向操作上的顶梁柱(其它的实现也实现了上述的功能,但是至少在nopCommerce_4.10应用程序中其开发者的是以Setting实体作为纵向上抽通道,在反向开发时使用Setting实体及其操作,实现起来更加的简单、直接和接近原开发者的思维)。而通过对其它的实体定义的类和方法所实现的功能是对Setting实体功能的横向的扩展(这也是Autofac中间件在nopCommerce_4.10应用程序中使用的意义之所在)。

5、在DependencyRegistrar.cs文件中同时定义了SettingsSource类它的功能是:对继承于ISettings接口的所有类和存储于数据库中设置表中的所有项的实例进行注册。其具体实现见源与本节相对应的源代码。

二、调用注册

  1. Core.Infrastructure.NopEngine类中添加保护方法:

#region 方法--私有/保护

        /// <summary>

        /// 【注册依赖】

        /// <param name="nopConfig">启动NOP配置实例。</param>

        /// <param name="services">服务描述者集合实例。</param>

        /// <param name="typeFinder">类型查找器实例。</param>

        /// // <returns>

        /// 返回:

        ///     返回,服务供应商实例。

        /// </returns>

        /// <remarks>

        /// 摘要:

        ///    通过使用Autofac实现注册依赖,返回服务供应商实例。

        /// </remarks>

        /// </summary>

        protected virtual IServiceProvider RegisterDependencies(NopConfig nopConfig, IServiceCollection services, ITypeFinder typeFinder)

        {

            var containerBuilder = new ContainerBuilder();

            //注册。

            containerBuilder.RegisterInstance(this).As<IEngine>().SingleInstance();

            //注册类型查找器实例。

            containerBuilder.RegisterInstance(typeFinder).As<ITypeFinder>().SingleInstance();

            //查找由其他程序集提供的依赖性注册。

            var dependencyRegistrars = typeFinder.FindClassesOfType<IDependencyRegistrar>();

            //创建和排序依赖注册的实例。

            var instances = dependencyRegistrars

                .Select(dependencyRegistrar => (IDependencyRegistrar)Activator.CreateInstance(dependencyRegistrar))

                .OrderBy(dependencyRegistrar => dependencyRegistrar.Order);

            //注册所有提供的依赖项。

            foreach (var dependencyRegistrar in instances)

                dependencyRegistrar.Register(containerBuilder, typeFinder, nopConfig);

            //使用一组注册的服务描述符填充Autofac容器生成器。

            containerBuilder.Populate(services);

            // 创建服务供应商。

            _serviceProvider = new AutofacServiceProvider(containerBuilder.Build());

            return _serviceProvider;

        }

 #endregion

2、修改ConfigureServices方法以调用依赖注册   

/// <summary>

        /// 【配置服务】

        /// <param name="services">服务集合实例。</param>

        /// <param name="configuration">应用程序配置实例。</param>

        /// <returns>

        /// 返回:

        ///     返回,服务供应商实例。

        /// </returns>

        /// <remarks>

        /// 摘要:

        ///    添加服务实例集合到应用程序,并配置服务供应商实例。

        /// </remarks>

        /// </summary>

        public IServiceProvider ConfigureServices(IServiceCollection services, IConfiguration configuration)

        {

            /*

                通过typeFinder.FindClassesOfType<INopStartup>()方法调用,

             继承/实现INopStartup接口的所有类的实例,这些类中就包含NopMvcStartup类,

             通过NopMvcStartup类调用Framework.Infrastructure.Extensions.ServiceCollectionExtensions类中的

             public static IMvcBuilder AddNopMvc(this IServiceCollection services)方法调用services.AddMvc();

             实现配置MVC服务。

             */

            var typeFinder = new WebAppTypeFinder();

            var startupConfigurations = typeFinder.FindClassesOfType<INopStartup>();

            //创建和排序启动配置实例。

            var instances = startupConfigurations

                .Select(startup => (INopStartup)Activator.CreateInstance(startup))

                .OrderBy(startup => startup.Order);

           //配置服务。

           foreach (var instance in instances)

               instance.ConfigureServices(services, configuration);

            //通过Autofac实现注册依赖。

            var nopConfig = services.BuildServiceProvider().GetService<NopConfig>();

            RegisterDependencies(nopConfig, services, typeFinder);

            return _serviceProvider;

 }

3、按F5发现依然能够正常启动默认的Home.Index页面。

到此为止我已经详细的剖析了nopCommerce_4.10应用程序通过Autofac中间件实现注册依赖,至于更新详细的信息请见我所上传代码“MyNopCommerce(不删,002_通过Autofac实现注册依赖)( https://download.csdn.net/download/zhoujian_911/10709011)”中的“日志”与“.vsdx”文件。

猜你喜欢

转载自blog.csdn.net/zhoujian_911/article/details/82986749
今日推荐