Castle Windsor Common Introduction and its application in ABP project

Source: Internet
Author: User
Tags log4net

Recently on the ABP project, see the Sun Ming Rui blog, ABP's di and AOP framework with Castle Windsor
The following is an introduction to the common methods of Castle Windsor Project and summary of the use of ABP

1. Download Castle.windsor required DLL, run Install-package in Package Manager console Castle.windsor

Let's look at a simple example below.

var container = new WindsorContainer (); container. Register (Component.for (typeof (Imyservice). Implementedby (typeof (Myserviceimpl));//control inversion Gets the instance var myservice= container. Resolve<imyservice> ();

We first created the WindsorContainer and then registered the Myserviceimpl and its interfaces, and then we created an instance of Myserviceimpl with the container.

2, registration Castle.windsor There are many ways to register your class, the following describes several methods of registration

General Registration

We can use Castle.MicroKernel.Registration.Component this static class, the For method to register, return a componentregistration, you can use him to further register
Register a class to a container, the default registration type is singleton, which is a singleton

Container. Register (    component.for<myserviceimpl> ());

Register a default instance of the interface, which is used in many of the ABP projects

Container. Register (    component.for (typeof (Imyservice)        . Implementedby (typeof (Myserviceimpl));

Of course, we can also specify the way to register instances, mainly transient and singleton,transient are each request to create a new instance, Singleton is a singleton, they are lifestyle properties

Container. Register (   component.for<imyservice> ()      . Implementedby<myserviceimpl> ()      . Lifestyle.transient);

When registering an interface with more than one instance, we can register it in a named way, the following is the case of no renaming, the default is to register the first Myserviceimpl

Container. Register (    component.for<imyservice> (). Implementedby<myserviceimpl> (),    component.for<imyservice> (). Implementedby<otherserviceimpl> ());

For example, the cache in a NOP project, but the NOP project is AUTOFAC, so you can reverse it by name.

Builder. Registertype<memorycachemanager> (). As<icachemanager> (). Named<icachemanager> ("Nop_cache_static"). SingleInstance (); builder. Registertype<perrequestcachemanager> (). As<icachemanager> (). Named<icachemanager> ("Nop_cache_per_request"). Instanceperlifetimescope ();

At Castle Windsor we can

Container. Register (    component.for<imyservice> (). Named ("Otherserviceimpl"). Implementedby<otherserviceimpl> ());

As mentioned above, the simplest registration method commonly used in Windsor projects, we can also register as an assembly, such as an instance registered with IController as an interface based on the current assembly.

Public windsorcontrollerfactory (IWindsorContainer container) {   This.container = container;   var controllertypes = from       T in assembly.getexecutingassembly (). GetTypes ()       where typeof (IController). IsAssignableFrom (t)       select T;       foreach (Var t in controllertypes)          container. Register (Component.for (t). lifestyle.transient);}

Assembly.getexecutingassembly () is to get the currently running assembly, or you can do the following, which is the ABP code

Context. IocManager.IocContainer.Register (                classes.fromassembly) (context. Assembly)                    . Includenonpublictypes ()                    . Basedon<isingletondependency> ()                    . Withservice.self ()                    . Withservice.defaultinterfaces ()                    . Lifestylesingleton ()                );

  

Custom Registration

You can also override the Iwindsorinstaller method install for unified registration

public class repositoriesinstaller:iwindsorinstaller{public    void Install (IWindsorContainer container, Iconfigurationstore store)    {        container. Register (classes.fromthisassembly ()                            . Where (component.isinsamenamespaceas<king> ())                            . Withservice.defaultinterfaces ()                            . Lifestyletransient ());}    }

Constructors & Attribute Injection

Constructor and attribute injection are best practices for project development, and you can use it to get the dependencies of your classes.

public class personappservice{Public    ILogger Logger {get; set;}    Private IPersonRepository _personrepository;    Public Personappservice (ipersonrepository personrepository)    {       _personrepository = personrepository;       Logger = nulllogger.instance;    }    public void Createperson (string name, int.)    {       logger.debug ("Inserting a new person to database with name =" + name);       var person = new Person {name = name, age = age};       _personrepository.insert (person);       Logger.debug ("Successfully inserted!");}    }

IPersonRepository is injected from the constructor, and the ILogger instance is injected from the public attribute. In this way, your code will not reflect the dependency injection system. This is the most appropriate way to use the DI system.

General Controller, we will be unified registration, the following is the ABP Registration controller code

public class windsorcontrollerfactory:defaultcontrollerfactory{private    ReadOnly Ikernel kernel;    Public windsorcontrollerfactory (Ikernel kernel) {this.kernel = kernel; } public override void Releasecontroller (IController controller) {kernel.    Releasecomponent (Controller);        } protected override IController GetControllerInstance (RequestContext requestcontext, Type controllertype) { if (Controllertype = = null) {throw new HttpException (404, String.        Format ("The Controller for path ' {0} ' could not being found.", RequestContext.HttpContext.Request.Path)); } return (IController) kernel.    Resolve (Controllertype); }}

The injection pattern using constructors is a perfect way to provide a class's dependency. In this way, only instances that rely on you to create a class are provided. And it's also a powerful way to explicitly declare what the class needs
Rely on to be able to work correctly. However, in some cases, the class relies on another class, but it can also be without it. This is usually appropriate for crosscutting concerns, such as logging. A class can have no logbook, but it can write logs if you provide a log object.
in this case, you can define dependencies as public properties, rather than having them put in constructors . ---from ABP Chinese documents

Well, to finally put Castle Windsor some commonly used registration is finished, the above is mainly about the dependency injection, the following start ABP related introduction

ABP defines a unified registration class Iocmanager, mainly provides registration, inversion, logoff and other operations

    public class Iocmanager:iiocmanager {public static iocmanager Instance {get; private set;}        Public IWindsorContainer Ioccontainer {get; private set;}        Private ReadOnly list<iconventionaldependencyregistrar> _conventionalregistrars;        Static Iocmanager () {Instance = new Iocmanager ();            } public Iocmanager () {ioccontainer = new WindsorContainer ();            _conventionalregistrars = new list<iconventionaldependencyregistrar> ();            Register self! Ioccontainer.register (Component.for<iocmanager, Iiocmanager, Iiocregistrar, iiocresolver> ().        Usingfactorymethod (() = this)); }//<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 Registerassemblyb Yconvention (Assembly Assembly, conventionalregistrationconfig config) {var context = new Conventionalre            Gistrationcontext (assembly, this, config); This loop is still four registered, foreach (var registerer in _conventionalregistrars) {registerer.            registerassembly (context); } if (config.            Installinstallers) {Ioccontainer.install (fromassembly.instance (assembly)); }        }

One important way is that registerassemblybyconvention loops through all classes that inherit the Iconventionaldependencyregistrar interface and registers

To view the code discovery for the ABP, the main implementation of the interface is four classes, respectively registering the Dbcontex type, the controller and the Apicontroller and registering the interface -based Classes implemented by Itransientdependency and Isingletondependency and Iinterceptor

Because of the length of the relationship, I only show the registration controller

    <summary>//    registers all MVC Controllers derived from <see cref= "Controller"/>.    </summary> public    class Controllerconventionalregistrar:iconventionaldependencyregistrar    {        <inheritdoc/> public        void registerassembly (Iconventionalregistrationcontext context)        {            Context. IocManager.IocContainer.Register (                classes.fromassembly) (context. Assembly)                    . Basedon<controller> ()                    . Lifestyletransient ()                );        }    }

About Castle.windsor Registration There is an entity, generally we commonly use singleton (singleton) and transient (each time a new object is created) so let's see what the ABP does.

    public enum Dependencylifestyle {//<summary>//        Singleton object. Created a single object on first resolving///        Same instance is used for subsequent resolves.        </summary>        Singleton,///        <summary>/        Transient object. Created one object for every resolving.        </summary>        Transient    }

Defines an enumeration of lifestyle for related registrations

    public void Register (type type, dependencylifestyle lifeStyle = Dependencylifestyle.singleton)    {        Ioccontainer.register (Applylifestyle (component.for (type), LifeStyle));    }

  

In addition Castle Windsor also support the log, which is also applied to the ABP, support log4net and so on first need to download the corresponding DLL, Install-package castle.windsor-log4net next automatically register a log instance
public class loggerinstaller:iwindsorinstaller{public    void Install (IWindsorContainer container, Iconfigurationstore store)    {        container. Addfacility<loggingfacility> (f = f.uselog4net ());}    }

The third configuration under the Log4net.config file, below is my simple configuration

<?xml version= "1.0" encoding= "Utf-8"?><configuration> <configSections> <!--Log configuration section--<se ction name= "log4net" type= "log4net. Config.log4netconfigurationsectionhandler,log4net "/> </configSections> <log4net> <root> &l    T;priority value= "All"/> <appender-ref ref= "Fileappender"/> <appender-ref ref= "InfoLoging"/> </root> <appender name= "Fileappender" type= "log4net. Appender.rollingfileappender "> <file value=" log\\log.txt "/> <appendtofile value=" true "/> & Lt;maxsizerollbackups value= "Ten"/> <maximumfilesize value= "10000KB"/> <rollingstyle value= "Size"/ > <staticlogfilename value= "true"/> <filter type= "log4net. Filter.levelrangefilter "> <levelmin value=" error "/> <levelmax value=" error "/> </fil ter> <lockingmodel type= "log4net.  Appender.fileappender+minimallock "/>    <layout type= "log4net. Layout.patternlayout "> <conversionpattern value="%date [%thread]%-5level%logger [%PROPERTY{NDC}]-%message %newline "/> </layout> </appender> <appender name=" infologing "type=" log4net.      Appender.rollingfileappender "> <file value=" log\\logdata.txt "/> <appendtofile value=" true "/> <maxsizerollbackups value= "Ten"/> <maximumfilesize value= "10000KB"/> <rollingstyle value= "Siz E "/> <staticlogfilename value=" true "/> <filter type=" log4net. Filter.levelrangefilter "> <levelmin value=" info "/> <levelmax value=" info "/> </filte r> <lockingmodel type= "log4net. Appender.fileappender+minimallock "/> <layout type=" log4net. Layout.patternlayout "> <conversionpattern value="%date [%thread]%-5level%logger [%PROPERTY{NDC}]-%message %newline "/> </layout> </appender>  </log4net></configuration> 

At the end of the article will be attached source code, including configuration

In the end, we can use it, and I'm using the attribute injection method.

    public class Accountcontroller:controller    {public        ILogger Logger {get; set;}        Public AccountController ()        {            Logger = nulllogger.instance;        }        Public ActionResult LogOn ()        {            logger.error ("test");            return View ();        }    }

Of course ABP is also available in this way with the log4net log, but it is driven by the time it is configured in global

Above is the application of the IOC of the Castle Windsor, and of course the AOP method is also useful in the ABP, we can inherit the Iinterceptor intercept method to intercept

namespace castle.dynamicproxy{    using System;        Public interface Iinterceptor    {        void Intercept (Iinvocation invocation);}    }

Below is a look at the most important interception method of the ABP

    Internal class Unitofworkinterceptor:iinterceptor {private ReadOnly Iunitofworkmanager _unitofworkmanager        ; Public Unitofworkinterceptor (Iunitofworkmanager unitofworkmanager) {_unitofworkmanager = Unitofworkmana        Ger        }//<summary>//intercepts a method. </summary>//<param name= "invocation" >method invocation arguments</param> public voi                D Intercept (iinvocation invocation) {if (_unitofworkmanager.current! = null) { Continue with current UOW invocation.                Proceed ();            Return } var unitofworkattr = Unitofworkattribute.getunitofworkattributeornull (invocation.            Methodinvocationtarget); if (unitofworkattr = = NULL | | unitofworkattr.isdisabled) {//no need to a UOW inv Ocation.                Proceed ();            Return }//no Current UOW, run a new one PERFORMUOW (invocation, unitofworkattr.createoptions ()); }

Its registration is registered in the module, the registration mainly contains irepository and Iapplicationservice and Unitofworkattribute, so contains [unitofwork] Methods and methods of inheriting irepository and Iapplicationservice will be blocked

        <summary>//Intercept registration events///</summary>//<param name= "key" &GT;&LT;/PARAM&G        T <param name= "Handler" ></param> private static void componentregistered (string key, Ihandler handler ) {if (Unitofworkhelper.isconventionaluowclass (handler).                Componentmodel.implementation) {//intercept All methods of all repositories. Handler.            COMPONENTMODEL.INTERCEPTORS.ADD (New Interceptorreference (typeof (Unitofworkinterceptor))); } else if (handler. ComponentModel.Implementation.GetMethods (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).  Any (Unitofworkhelper.hasunitofworkattribute)) {//intercept All methods of classes those has at                Least one method that has unitofwork attribute.                Todo:intecept only unitofwork methods, not other methods! Handler. COMPONENTMODEL.INTERCEPTORS.ADD (New Interceptorreference (typeof (Unitofworkinterceptor)); }        }

The above will be Castle Windsor common functions and the use of ABP project is simply finished. Main references for several projects ABP, NOP, Prodinner

Simple Source Address: Http://pan.baidu.com/s/1kTCNpQZ

Reference article:

Https://github.com/ABPFrameWorkGroup/AbpDocument2Chinese

Https://github.com/castleproject/Windsor/blob/master/docs/README.md

Http://www.cnblogs.com/wucg/archive/2012/03/09/2387946.html

Castle Windsor Common Introduction and its application in ABP project

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.