Dependency Injection Framework AUTOFAC type registration and simple use

Source: Internet
Author: User

AUTOFAC

AUTOFAC is a set of efficient dependency injection frameworks.

AUTOFAC Official website: http://autofac.org/

AUTOFAC Open Source project on GitHub: HTTPS://GITHUB.COM/AUTOFAC/AUTOFAC

AUTOFAC installation: Through vs NuGet can be easily obtained.

Ioc/di

On the concept of IOC and DI, there are a lot of related blogs online, you can understand a little bit, compare.

My personal understanding is to follow the English translation of the Chinese to understand:

Ioc:inversion of control inversion, inversion of control, initialization of the object controlled by the external IOC container;

Di:dependency injection relies on injection to initialize other objects that the object relies on by injecting.


Simple example


Let's start with a simple example to see the basic use of AUTOFAC and some concepts:


Class Program
{
static void Main (string[] args)
{
var builder = new Containerbuilder ();
Builder.    Registertype<class_1> (); Registering class_1 in the AUTOFAC container

IContainer container = Builder. Build ();
Class_1 obj = container. Resolve<class_1> (); To get the Class_1 object from the AUTOFAC container
Console.WriteLine (obj. ID);

Console.Write ("Press any key to continue ...");
Console.readkey ();
}
}




Class Class_1
{
Public Guid Id {get; set;}

Public Class_1 ()
{
Id = Guid.NewGuid ();
}
}



The code above demonstrates the simplest way to register/acquire. We first type registration through Containerbuilder, and then we can get the type instance through IContainer later. Here we also understand that the type is required to register the advanced line, and then can be obtained through the AUTOFAC (followed by a number of special configuration, but this also belongs to the alternative way of registration).

Then we know that in AUTOFAC, the type registration is done first through the Containerbuilder, and then the Containerbuilder build method is used to get the IContainer type instance. The IContainer instance can then be used to get the instance object of the registered type.


AUTOFAC Type Registration

Type/Generics Registration

In a simple example, we have seen a way of registering, that is, generics registration:

Builder. Registertype<class_1> ();

This registration method is very convenient and simple, more commonly used, but there is a disadvantage is that the type of registration must be in the current project or by the current project reference, because the use of generics, must be type-specific. For this, there is also a way to register through a type object:

String is a type full name
Builder. Registertype (Type.GetType ("Autofacblog.class_1"));

Type registration is used in this way, and the registered type may not be directly referenced, but note that the assembly of the type must be loaded.

This registration method is used when there is a plug-in or similar need to dynamically load an assembly, by scanning the assembly, obtaining some types that meet the specified criteria, to register.


Assembly Bulk Registration

The type registration refers to the scanning of assemblies to obtain partial types for registration. AUTOFAC provides a convenient way for you to filter type registrations directly from the assembly:

Gets the current application load assembly (used in C/s applications)
var assembly = assembly.getexecutingassembly ();
var builder = new Containerbuilder ();
Builder. Registerassemblytypes (assembly); Register non-static types defined by all assembly classes

In the preceding code, all of the custom non-static types in the assembly are registered to AUTOFAC through the Registerassemblytypes method, and the IContainer object can be used to obtain all the custom type objects in the assembly.

This is achieved in bulk, but usually we do not need to register all types, so AUTOFAC provides several ways to filter:

Builder. Registerassemblytypes (Assembly)
. Where (type => type). Namespace.equals ("Iocautofac.example")); Conditional judgment

This approach is believed that everyone is familiar with the WHERE+LAMBDA way to make conditional judgments, lambda parameters are type types, that is, the assembly of type.

Builder. Registerassemblytypes (Assembly)
.  Except<program> (); Excluding program types

This method is used to exclude a specified type of registration, which is more applicable when fewer cases are excluded. There is another use for except, but the usage is more complex and is not introduced here.

Builder. Registerassemblytypes (Assembly)
.  Innamespace ("Iocautofac.example"); Type is in the Iocautofac.example namespace

The registered type needs to be in the specified namespace.

Builder. Registerassemblytypes (Assembly)
.  Innamespaceof<program> (); Type is in the namespace in which the program is located.

This approach is similar to the one above, and is also used to determine namespaces, which are based on the type to get the namespace.



In this way, we can bulk register the types in the assembly, type/generics in the case of a less registered type is good, but when the type of a lot of registration, one of the handwriting registration will appear very powerless, this is the time to register the assembly volume.


Lambda Registration

Both of the ways mentioned above are registered directly by type, which, when acquired, will be created directly from the constructor (the preferred selection for the constructor is described in a later blog post) and no more action will be done. Sometimes, when we want to be able to do more things automatically when we get objects, we can address them by Lambda registration:


Builder. Register (CC =>
{
var clas1 = new Class_1 ();
while (CLAS1. Id.tostring (). Contains ("a"))
{
CLAS1. Id = Guid.NewGuid ();
}
return CLAS1;
});



The above code actually registers the Class_1 type because the last object type returned is Class_1.

The Register method receives a lambda expression as an argument, and in a lambda expression we can do a lot of things, including some attribute injections (subsequent instructions), method injection (follow-up instructions), conditional judgments, and so on.

We actually execute an expression like this when we get the Class_1 object through AUTOFAC. In addition, the type of the parameter cc of the lambda expression is icomponentcontext, where we can use it simply as a icontainer.


Instance Registration

var clas1 = new Class_1 ();
CLAS1. Id = Guid.Empty;

Builder. RegisterInstance (CLAS1);

By RegisterInstance For instance registration, we need to note that instance registration can be used as a singleton registration, that is, when you get the Class_1 object later by AUTOFAC, you get the object when you register. Also, if one modifies the object somewhere, the other gets the modified object when it is retrieved elsewhere.


Module Registration

In daily development, it is possible that different development will be responsible for different modules for individual development. In the development process, different modules may have their own type of development needs to be registered in the AUTOFAC, but if everyone is registered, to modify a specified place of code, this is in the code merge, it is painful. Better yet, each development of different modules has its own specified type registration area, which reduces a lot of code conflicts when code is merged.

For this way, AUTOFAC has provided us with:


Class Program
{
static void Main (string[] args)
{
var builder = new Containerbuilder ();

Builder. Registermodule<modulea> ();
Both types of registration have the same effect
Builder. Registermodule (New Moduleb ());

IContainer container = Builder. Build ();
Class_1 CLAS1 = container. Resolve<class_1> ();
Class_2 CLAS2 = container. Resolve<class_2> ();
Console.WriteLine (CLAS1. ID);
Console.WriteLine (CLAS2. ToString ());

Console.Write ("Press any key to continue ...");
Console.readkey ();
}
}


Class Modulea:module
{
protected override void Load (Containerbuilder builder)
{
Builder. Registertype<class_1> ();
}
}

Class Moduleb:module
{
protected override void Load (Containerbuilder builder)
{
Builder. Registertype<class_2> ();
}
}



Class Class_2
{

}

In the preceding code, there are two classes that inherit from the module class: Modulea, Moduleb, which override the parent's Load method and register the Class_1 and class_2 types in the Load method. The module is then registered with Registermodule in the main program.

In this way, different development can each create a class to inherit from the module, and then rewrite the Load method, the Load method for its own type registration, and finally the unified registration of module.

Module Note Description

In fact, the parameters required by Registermodule are not inherited from the module class, but rather the class that implements the IModule interface, and the module implements the IModule interface. That is, we can also write a type that implements the IModule interface and then pass it in when Registermodule. But generally we directly to inherit the module is good, this way is relatively simple and convenient, the way to achieve imodule more complex, of course, the function is also more, this will not be introduced.


Assembly Module Registration

Module registration, for many people to develop a convenient way to register, but we can also find that this way, still need to register module manually, if the module is too much, module registration code will appear more and miscellaneous, of course, can be manually managed to control the amount of module. But AUTOFAC also provides a more convenient way, and for a similar Orchard module development (sub modules with the main module without reference relationship, loading the child module by assembly loading) or plug-in development, We have no way to register a module without a direct reference relationship through Registerodule.

For the above scenario, AUTOFAC provides a good way to address:

var builder = new Containerbuilder ();
var assembly = assembly.getexecutingassembly ();
Builder. Registerassemblymodules (assembly);

The code above registers all the types of imodule interfaces that are implemented in the Assembly assembly (which is also counted as multi-layer inheritance), so that all we need to do is take out all the assemblies and then register them through Registerassemblymodules. You can automatically register all of the module.

Registerassemblymodule can also specify a generic type:

Builder. Registerassemblymodules<modulea> (assembly);

This is registered to specify that only the module that inherits from Modulea is registered in the Assembly assembly.


End Statement

This article mainly tells AUTOFAC in the comparison commonly used also relatively good registration way, and did not all registers the way to tell.

It is highly recommended that you use module, each of which has its own module, so that a module has a fixed unknown that makes it easy to find registrations and dependencies in the project.

Through this article, you can learn several common registration methods, as well as the simplest way to obtain the object, beginners can simply try.


Simple use of AUTOFAC-dependent injection framework


1 decompression of its compressed package, mainly see Autofac.dll,autofac.configuration.dll, this is also the focus of this article Autofac class library.

2 Create a console project and refer to the above DLL file. Create a database operation interface IDatabase.cs:

<summary>
Database operate interface
</summary>
public interface Idatabase
{
String Name {get;}

void Select (string commandtext);

void Insert (string commandtext);

void Update (string commandtext);

void Delete (string commandtext);
}


This contains a method for crud four operations.



3 Create two types of database operation classes, SqlDatabase.cs and OracleDatabase.cs:

public class Sqldatabase:idatabase
{
public string Name
{
get {return "SQL Server";}
}

public void Select (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is a query SQL in {1}!", CommandText, Name));
}

public void Insert (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is an insert SQL in {1}!", CommandText, Name));
}

public void Update (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is an update SQL in {1}!", CommandText, Name));
}

public void Delete (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is a delete sql in {1}!", CommandText, Name));
}
}


And

public class Oracledatabase:idatabase
{
public string Name
{
get {return "Oracle";}
}

public void Select (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is a query SQL in {1}!", CommandText, Name));
}

public void Insert (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is an insert SQL in {1}!", CommandText, Name));
}

public void Update (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is an update SQL in {1}!", CommandText, Name));
}

public void Delete (string commandtext)
{
Console.WriteLine (String. Format ("' {0} ' is a delete sql in {1}!", CommandText, Name));
}
}



4) Then create a database manager DatabaseManager.cs:


public class Databasemanager
{
Idatabase _database;

Public Databasemanager (Idatabase database)
{
_database = database;
}

public void Search (string commandtext)
{
_database. Select (CommandText);
}

public void Add (string commandtext)
{
_database. Insert (CommandText);
}

public void Save (string commandtext)
{
_database. Update (CommandText);
}

public void Remove (string commandtext)
{
_database. Delete (CommandText);
}

}



5 in the console, write the following test procedures:

var builder = new Containerbuilder ();
Builder. Registertype<databasemanager> ();
Builder. Registertype<sqldatabase> (). As<idatabase> ();
using (var container = Builder. Build ())
{
var manager = container. Resolve<databasemanager> ();
Manager. Search ("SELECT * FORM USER");
}




Run Result:



Analysis:

Here the Databasemanager is registered through the Containerbuilder method Registertype, and the registered type can resolve your Databasemanager instance in the corresponding container.

Builder. Registertype<sqldatabase> (). As<idatabase> (); as allows the Databasemanager class to rely on a constructor to depend on the corresponding interface of the injected type.

The build () method generates a corresponding container instance so that it can be resolved to the registered type instance through resolve.



Similarly, if you modify the database type to register as:

Builder. Registertype<oracledatabase> (). As<idatabase> ();

Run Result:




6 obviously in the above program, SQLDatabase or oracledatabase has been exposed to the client program, and now I want to select the type to read through the file configuration. AUTOFAC has a Autofac.Configuration.dll that is very convenient to configure the type to avoid recompiling the program.

Modify App.config:

<configuration>
<configSections>
<section name= "AUTOFAC" type= "Autofac.Configuration.SectionHandler, autofac.configuration"/>
</configSections>
&LT;AUTOFAC defaultassembly= "Autofacdemo" >
<components>
<component type= "autofacdemo.sqldatabase, Autofacdemo" service= "Autofacdemo.idatabase"/>
</components>
</autofac>
</configuration>


The component is processed through the Autofac.Configuration.SectionHandler configuration node.

The corresponding client program is changed to:

var builder = new Containerbuilder ();
Builder. Registertype<databasemanager> ();
Builder. Registermodule (New Configurationsettingsreader ("AUTOFAC"));
using (var container = Builder. Build ())
{
var manager = container. Resolve<databasemanager> ();
Manager. Search ("SELECT * FORM USER");
}


Run Result:


7 There is another way to register through the Register method:

var builder = new Containerbuilder ();
Builder. Registertype<databasemanager> ();
Builder. Registermodule (New Configurationsettingsreader ("AUTOFAC"));
Builder. Register (c => New Databasemanager (C.resolve<idatabase> ()));
using (var container = Builder. Build ())
{
var manager = container. Resolve<databasemanager> ();
Manager. Search ("SELECT * FORM USER");
}


The result is the same.



8 Now I want to use a user class to control the operation of permissions, such as adding or deleting the right to change, create a user class:

<summary>
Id Identity Interface
</summary>
public interface Identity
{
int Id {get; set;}
}


public class User:identity
{
public int Id {get; set;}
public string Name {get; set;}
}


To modify the DatabaseManager.cs code:

public class Databasemanager
{
Idatabase _database;
User _user;

Public Databasemanager (Idatabase database): This (database, NULL)
{
}

Public Databasemanager (idatabase database, user user)
{
_database = database;
_user = user;
}

<summary>
Check Authority
</summary>
<returns></returns>
public bool Isauthority ()
{
BOOL result = _user!= null && _user. Id = = 1 && _user. Name = = "Leepy"? True:false;
if (!result)
Console.WriteLine ("Not authority!");

return result;
}

public void Search (string commandtext)
{
_database. Select (CommandText);
}

public void Add (string commandtext)
{
if (isauthority ())
_database. Insert (CommandText);
}

public void Save (string commandtext)
{
if (isauthority ())
_database. Update (CommandText);
}

public void Remove (string commandtext)
{
if (isauthority ())
_database. Delete (CommandText);
}
}


A parameter user was added to the constructor, and Add,save,remove increased the permission judgment.

To modify a client program:

User User = new User {Id = 1, Name = "Leepy"};
var builder = new Containerbuilder ();
Builder. Registermodule (New Configurationsettingsreader ("AUTOFAC"));
Builder. RegisterInstance (user). As<user> ();
Builder. Register (c => New Databasemanager (c.resolve<idatabase> (), c.resolve<user> ()));

using (var container = Builder. Build ())
{
var manager = container. Resolve<databasemanager> ();

Manager. ADD ("INSERT into USER ...");
}


Run Result:


Analysis:

Builder. RegisterInstance (user). As<user> (), registering the User instance.

Builder. Register (c => New Databasemanager (c.resolve<idatabase> (), c.resolve<user> ())); Registers an Databasemanager instance with a LAMPDA expression.

If I modify the user's attribute value here:

User User = new User {Id = 2, Name = "Zhangsan"};

Run Result:

Indicates that the user does not have permission to operate.

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.