ABP Module Design

Source: Internet
Author: User
Tags nopcommerce

ABP Module Design

Back to ABP Series

The ABP is "ASP. Boilerplate Project (ASP. NET Template project) "for short.

ASP. Boilerplate is a new starting point for developing modern web applications with best practices and popular technologies, and is designed to be a common Web application framework and project template.

ABP's official website: http://www.aspnetboilerplate.com

ABP Official Document: Http://www.aspnetboilerplate.com/Pages/Documents

Open source project on GitHub: Https://github.com/aspnetboilerplate

I. Summary

Both orchard and Nopcommerce should be aware of the modular concept, and the ABP module is one of them. The principle of implementation is the same: the application is generally defined module interface, and then put the module compiled DLL into a fixed directory (ABP can only be placed under the bin), the application main program by loading those implementation of the plug-in interface DLL to implement plug-in use.

The ABP framework provides the basis for creating and assembling modules that can be relied upon by another module. In general, an assembly can be seen as a module. In the ABP framework, a module is defined by a class, and this class inherits from Abpmodule.

Nopcommerce plug-in implementation can be: ASP. NET MVC5 plug-in mechanism to understand the simple implementation.

Ii. Basic Concepts

In the following example, we develop a mybolgapplication module that can be called in several different applications, with the following code:

        public class Myblogapplicationmodule:abpmodule//Definition        {public            override void Initialize ()//initialization            {                Iocmanager.registerassemblybyconvention (assembly.getexecutingassembly ());                This line of code is basically the same. Its purpose is to register a specific class or interface of the current assembly into a dependency injection container.            }        }

The ABP framework scans all the assemblies and discovers all the classes in the Abpmodule class that have already been imported, and if you have already created an app with multiple assemblies, our recommendation for ABP is to create a module for each assembly.

Life cycle:

In one application, the ABP framework invokes some of the specified methods of module modules for starting and shutting down the module. We can overload these methods to accomplish our own task.

The ABP framework invokes these methods in the order of dependencies, assuming that module a relies on module B, then module B is initialized before module A, and the module starts with the following sequence of methods:


1, Preinitialize-b
2, Preinitialize-a
3, Initialize-b
4, Initialize-a
5, Postinitialize-b
6, Postinitialize-a

Here is a description of the specific method:

preinitialize Pre-initialization : This method is called the first time after the app is started. You can specify your own special code in this method before dependency injection registration. For example: If you create a traditional registration class, then you have to register the class (using Iocmanager to register the registration Class), you can register the event to the IOC container.

Initialize initialization : In this method is generally to carry out the registration of dependency injection, generally we through iocmanager.registerassemblybyconvention this method to achieve. If you want to implement a custom dependency injection, then refer to the relevant documentation for dependency injection.

postinitialize Commit initialization: The last method used to parse dependencies.

shutdown off: This method is called when the app is closed.

Module dependencies:

The ABP framework automatically resolves dependencies between modules, but we recommend that you explicitly declare dependencies by overloading the Getdependencies method.

[DependsOn (typeof (Myblogcoremodule))]//defining dependencies by annotations public class myblogapplicationmodule:abpmodule{public    override void Initialize ()    {        iocmanager.registerassemblybyconvention (assembly.getexecutingassembly ());}    }

For example, the above code, we declare the dependencies of Myblogapplicationmodule and Myblogcoremodule (through the property attribute), Myblogapplicationmodule This application module relies on the Myblogcoremodule core module, and the Myblogcoremodule core module is initialized before the Myblogapplicationmodule module.

Custom Module methods:

The modules we define ourselves may have methods that are called by other modules that depend on the current module, and the following example assumes that Module 2 relies on Module 1 and wants to invoke the method of Module 1 at pre-initialization time.

public class mymodule1:abpmodule{public    override void Initialize ()//Initialize module    {        Iocmanager.registerassemblybyconvention (assembly.getexecutingassembly ());//here, register for Dependency injection.    }    public void MyModuleMethod1 ()    {        //write the custom method here.    }} [DependsOn (typeof (MyModule1))]public class mymodule2:abpmodule{    private readonly MyModule1 _mymodule1;    Public MyModule2 (MyModule1 myModule1)    {        _mymodule1 = myModule1;    }    public override void Preinitialize ()    {        _mymodule1.mymodulemethod1 ();//method to invoke MyModuleMethod1.    }    public override void Initialize ()    {        iocmanager.registerassemblybyconvention ( Assembly.getexecutingassembly ());}    }

In this way, the module 1 is injected into Module 2, so that Module 2 can call the method of Module 1.

Third, the basic principle

1. Get all DLLs under Bin

            <summary>            ///Get bin under all DLLs            ////</summary> public list<assembly> getallassemblies ()            {                var allreferencedassemblies = Buildmanager.getreferencedassemblies (). Cast<assembly> (). ToList ();                var dllfiles = directory.getfiles (Httpruntime.appdomainapppath + "bin\\", "*.dll", searchoption.topdirectoryonly). ToList ();                Return Dllfiles.select (Dllfile = allreferencedassemblies.firstordefault (asm = Assemblyname.referencematchesdefinition (ASM. GetName (), Assemblyname.getassemblyname (Dllfile))). Where (locatedassembly = locatedassembly = null). ToList ();            }

2, judge whether to inherit the Abpmodule interface

            <summary>/            //Determine if the types is related to Abpmodule            //</summary> public            static bool Isabpmodule (Type Type)            {                return                    type. IsClass &&                    !type. IsAbstract &&                    typeof (Abpmodule). IsAssignableFrom (type);            }

3. Cyclic related dependencies, fill them in the Modules collection

#region Loop-dependent dependencies, fill them in to the Modules collection in private static icollection<type> Addmissingdependedmodules (ICOLLECTION&L T                Type> allModules) {var initialmodules = allmodules.tolist ();                foreach (var module in initialmodules) {filldependedmodules (module, allModules);            } return allModules;                } private static void Filldependedmodules (Type module, icollection<type> allModules) { foreach (Var dependedmodule in Abpmodule.finddependedmoduletypes (module)) {if (                    Allmodules.contains (Dependedmodule)) continue;                    Allmodules.add (Dependedmodule);                Filldependedmodules (Dependedmodule, allModules);                }} public static list<type> finddependedmoduletypes (Type moduletype) { if (!            Isabpmodule (Moduletype))    {throw new Abpinitializationexception ("This type was not a ABP module:" + moduletype.assemblyqual                Ifiedname);                } var list = new list<type> ();                if (!moduletype.isdefined (typeof (Dependsonattribute), true)) return list; var dependsonattributes = Moduletype.getcustomattributes (typeof (Dependsonattribute), true).                Cast<dependsonattribute> (); List.                AddRange (dependsonattributes.selectmany (dependsonattribute = dependsonattribute.dependedmoduletypes));            return list; } #endregion

4. Control reversal

Using system;using system.collections.generic;using system.linq;using system.reflection;using    Abp.configuration.startup;using abp.dependency;using castle.core.logging;namespace Abp.Modules{//<summary>    This class is used to manage modules. </summary> Internal class Abpmodulemanager:iabpmodulemanager {public ILogger Logger {get; set;        } private readonly abpmodulecollection _modules;        Private ReadOnly Iiocmanager _iocmanager;        Private ReadOnly Imodulefinder _modulefinder; Public Abpmodulemanager (Iiocmanager Iocmanager, Imodulefinder modulefinder) {_modules = new Abpmoduleco            Llection ();            _iocmanager = Iocmanager;            _modulefinder = Modulefinder;        Logger = nulllogger.instance;        }///<summary>//initialization module///</summary> public virtual void initializemodules () {Loadall ();//load all var sortedmodules = _mOdules.            Getsortedmodulelistbydependency (); Initializes the event Sortedmodules.foreach of the modules (module-= module.            Instance.preinitialize ()); Sortedmodules.foreach (module = module.            Instance.initialize ()); Sortedmodules.foreach (module = module.        Instance.postinitialize ());        }///<summary>//Shutdown module///</summary> public virtual void shutdownmodules () {var sortedmodules = _modules.            Getsortedmodulelistbydependency ();            Sortedmodules.reverse (); Sortedmodules.foreach (sm = SM).        Instance.shutdown ()); }//<summary>////</summary> private void Loadall () {Log Ger.            Debug ("Loading Abp modules ...");            var moduletypes = Addmissingdependedmodules (_modulefinder.findall ());            Logger.debug ("Found" + moduletypes.count + "ABP modules in total."); Register to the IOC container foreach (var moduleType in Moduletypes) {if (! Abpmodule.isabpmodule (Moduletype)) {throw new Abpinitializationexception ("This type is                Not an ABP module: "+ moduletype.assemblyqualifiedname); } if (!_iocmanager.isregistered (Moduletype)) {_iocmanager.register (modul                EType);                }}//module added to _modules foreach (Var moduletype in moduletypes) {                var moduleobject = (abpmodule) _iocmanager.resolve (Moduletype);                Moduleobject.iocmanager = _iocmanager;                Moduleobject.configuration = _iocmanager.resolve<iabpstartupconfiguration> (); _modules.                ADD (New Abpmoduleinfo (ModuleObject));            Logger.debugformat ("Loaded module:" + moduletype.assemblyqualifiedname);            } ensurekernelmoduletobefirst ();            Setdependencies (); Logger.debugformat ("{0} Modules loaded. ", _modules.        Count); }//<summary>//Abpkernelmodule must be the first module///</summary> privat e void Ensurekernelmoduletobefirst () {var kernelmoduleindex = _modules.            FindIndex (m = M.type = = typeof (Abpkernelmodule));                if (Kernelmoduleindex > 0) {var kernelmodule = _modules[kernelmoduleindex]; _modules.                RemoveAt (Kernelmoduleindex); _modules.            Insert (0, Kernelmodule);                }} private void Setdependencies () {foreach (var moduleinfo in _modules) { Set dependencies According to Assembly dependency foreach (Var referencedassemblyname in Modu LeInfo.Assembly.GetReferencedAssemblies ()) {var referencedassembly = Assembly.Load (refe                    Rencedassemblyname); var dependedmodulelist = _modules. Where (M = m.assembly = = referencedassembly).                    ToList (); if (Dependedmodulelist.count > 0) {moduleInfo.Dependencies.AddRange (depended                    Modulelist);                }}//set dependencies for defined Dependsonattribute attribute (s).                    foreach (Var dependedmoduletype in Abpmodule.finddependedmoduletypes (Moduleinfo.type)) { var dependedmoduleinfo = _modules.                    FirstOrDefault (m = M.type = = Dependedmoduletype); if (Dependedmoduleinfo = = null) {throw new Abpinitializationexception ("Could No                    T find a depended module "+ Dependedmoduletype.assemblyqualifiedname +" for "+ moduleInfo.Type.AssemblyQualifiedName); } if ((ModuleInfo.Dependencies.FirstOrDefault (dm = DM). Type = = dependedmoduletype) = = null)) {Moduleinfo.dependencieS.add (Dependedmoduleinfo); }}}} private static icollection<type> Addmissingdependedmodules (icollecti            On<type> allModules) {var initialmodules = allmodules.tolist ();            foreach (var module in initialmodules) {filldependedmodules (module, allModules);        } return allModules; } private static void Filldependedmodules (Type module, icollection<type> allModules) {Fore Ach (var dependedmodule in Abpmodule.finddependedmoduletypes (module)) {if (!allmodules.contains                (Dependedmodule))                    {Allmodules.add (dependedmodule);                Filldependedmodules (Dependedmodule, allModules); }            }        }    }}

Iv. how to describe the module at the bottom of ABP

Abpmodule: Module Abstract class

Abpmoduleinfo: module Information

Collection of Abpmodulecollection:abpmoduleinfo

Iabpmodulemanager: module Management interface

Abpmodulemanager: Module Management class implements module management interface

Imodulefinder: Responsible for finding the interface of all modules

Defaultmodulefinder: Implementing the Imodulefinder Interface

Dependsonattribute: Used to define the ABP module dependent on other modules

Abpmoduleinfo is used to encapsulate The basic information of abpmodule. abpmodulecollection is a collection of Abpmoduleinfo.

V. Module registration to ABP bottom-level process

The ABP underlying framework discovers that the module is starting from Abpbootstrapper when executing the Initialize method, which invokes the Initializemodules method of the Iabpmodulemanager instance, This method then calls Defaultmodulefinder's FindAll method (which is used to filter out Abpmodule assembly), and FindAll method calls TypeFinder get all assembly. So as long as you have a class that inherits to Abpmodule in your defined assembly, and the assembly is referenced to your project, then this module can be said to be integrated by the ABP underlying framework.

ABP Module Design

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.