基于DDD的.NET开发框架 - ABP依赖注入

返回ABP系列html

ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。git

ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。github

ABP的官方网站:http://www.aspnetboilerplate.com数据库

ABP官方文档:http://www.aspnetboilerplate.com/Pages/Documents编程

Github上的开源项目:https://github.com/aspnetboilerplate设计模式

1、依赖注入概念

控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转通常分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较普遍。框架

依赖注入是一种软件设计模式的一个或多个依赖项注入(或服务),或经过引用传递,为依赖对象(或客户)和客户端状态的一部分。模式之间创建一个客户的依赖关系的行为,它容许程序设计是松散耦合的,依赖倒置和单一职责原则。它直接对比service locator模式,它容许客户了解他们所使用的系统找到依赖。ide

依赖注入不是目的,它是一系列工具和手段,最终的目的是帮助咱们开发出松散耦合、可维护、可测试的代码和程序。这条原则的作法是你们熟知的面向接口,或者说是面向抽象编程。函数

理想的软件开发设计是“高内聚,低耦合”,高内聚侧重面向对象编程,低耦合侧重面向接口编程,控制反转、依赖注入、依赖倒置都蕴含着面向接口编程的思想。工具

控制反转把传统上由程序代码直接操控的对象的调用权交给容器,经过容器来实现对象组件的装配和管理。所谓的"控制反转"概念就是对组件对象控制权的转移,从程序代码自己转移到了外部容器。

依赖注入是经过反射(reflection)动态的向某个对象提供它所须要的其余对象、

经常使用依赖注入框架:

Unity:微软patterns&practicest团队开发的IOC依赖注入框架,支持AOP横切关注点。

MEF(Managed Extensibility Framework):是一个用来扩展.NET应用程序的框架,可开发插件系统。

Spring.NET:依赖注入、面向方面编程(AOP)、数据访问抽象,、以及ASP.NET集成。

Autofac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性。

PostSharp:实现静态AOP横切关注点,使用简单,功能强大,对目标拦截的方法无需任何改动。

Castle Windsor、StructureMap、Ninject

其实我感受Autofac挺好用的,一直用的Autofac,不知道到Castle Windsor怎么样。

2、三层和DDD分层依赖关系

一、三层分层依赖以下图:

从引用关系咱们就能知道各层的依赖关系:BLL须要依赖DAL,由于BLL中用到了DAL层的实体。UI这一层须要依赖BLL,还须要依赖DAL,由于在UI中也用到了DAL层实体。

若是从换个数据库,DAL须要修改,那DAL的依赖也须要修改。

二、DDD分层依赖关系图

从上图能够知道,表现层和数据访问层都依赖领域模型层,这样的话,若是咱们新添加一个UI界面;更换一种数据源的存储和获取方式,只须要修改对应层的代码便可,领域模型层保持了稳定。

减小new引入的依赖及紧耦合最好的方式是使用构造函数注入依赖这种设计模式:即若是咱们须要一个依赖的实例,经过构造函数注入。

解耦和最重要的原则就是依赖倒置原则:

高层模块不该该依赖底层模块,他们都应该依赖抽象。抽象不该该依赖于细节,细节应该依赖于抽象。

简单理解就是组件应该依赖于接口而不是实现。

3、ABP依赖注入底层实现

ABP依赖注入是经过Castle Windsor依赖注入的框架实现。

一、经过实现IConventionalDependencyRegistrar的实例定义注入的约定,而后经过IocManager来读取这个规则完成依赖注入

代码在Abp项目文件的Dependency文件夹下

 1)在PreInitialize方法中给IocManager的IConventionalDependencyRegistrar的list中加入BasicConventionalRegistrar

IocManager.AddConventionalRegistrar(new BasicConventionalRegistrar());

2)IocManager维护了一个叫_conventionalRegistrars的list,其中的元素类型就是IConventionalDependencyRegistrar。接着IocManager的RegisterAssemblyByConvention是在模块的Initialize方法中被调用

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());            
        }

3)IocManager在RegisterAssemblyByConvention方法中遍历这个list,并根据IConventionalDependencyRegistrar的实例中定义的规则来完成register。

        /// <summary>
        /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method.
        /// </summary>
        /// <param name="assembly">Assembly to register</param>
        public void RegisterAssemblyByConvention(Assembly assembly)
        {
            RegisterAssemblyByConvention(assembly, new ConventionalRegistrationConfig());
        }

        /// <summary>
        /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method.
        /// </summary>
        /// <param name="assembly">Assembly to register</param>
        /// <param name="config">Additional configuration</param>
        public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config)
        {
            var context = new ConventionalRegistrationContext(assembly, this, config);

            foreach (var registerer in _conventionalRegistrars)
            {
                registerer.RegisterAssembly(context);
            }

            if (config.InstallInstallers)
            {
                IocContainer.Install(FromAssembly.Instance(assembly));
            }
        }

 

二、直接使用IocManager的Register方法直接完成注入

AbpModule有个受保护的IocManager的成员,因此AbpModule的派生类均可以使用这个IocManager完成注册。

public class AbpWebModule : AbpModule
    {
        /// <inheritdoc/>
        public override void PreInitialize()
        {
            if (HttpContext.Current != null)
            {
                XmlLocalizationSource.RootDirectoryOfApplication = HttpContext.Current.Server.MapPath("~");
            }
            //IocManager直接注入
            IocManager.Register<IAbpWebModuleConfiguration, AbpWebModuleConfiguration>();

            Configuration.Localization.Sources.Add(
                new DictionaryBasedLocalizationSource(
                    AbpWebLocalizedMessages.SourceName,
                    new XmlEmbeddedFileLocalizationDictionaryProvider(
                        Assembly.GetExecutingAssembly(), "Abp.Web.Localization.AbpWebXmlSource"
                        )));
        }

        /// <inheritdoc/>
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());            
        }
    }
相关文章
相关标签/搜索