The content is mainly translated from official documents, please see: http://autofac.readthedocs.org/en/latest/getting-started/index.html#application-startup
Integrate AUTOFAC into your app's basic mode:
- construct an application architecture based on inversion of control (IoC) in mind
- add AUTOFAC reference.
- in App launch configuration flow ...
- Create a containerbuilder.
- Registration component (components).
- build defined Containerbuilder build AUTOFAC container and store it for later use.
- While the program is running ...
-
- use life cycle domain to resolve component instances.
/ul>
This guide will use a console program step by step to demonstrate how to use AUTOFAC. Once you have a basic understanding, you can view more advanced usage and techniques at the following wiki sites: integration information for WCF, ASP. NET, and other application types.
Building an Application architecture
an IOC-based idea should be when an object is created, it is passed to it by an external entity that controls all objects in the system, instead of tying all the classes together, passing the instance through dependency new each time . If you want to learn more please see:Martin Fowler have an excellent article explaining dependency injection/inversion of control.
For our sample application, we will define a class that outputs the current date. However, we don't want it to be tied to the console because we want to be able to test it later or in a place where there is no console program.
We will also try to abstract the mechanism of the output date so that we can reuse it later.
We're going to do something like this:
usingSystem;namespacedemoapp{//This interface helps decouple the concept of//"Writing output" from the Console class. We//don ' t really "care" how the Write operation//happens, just that we can write. Public InterfaceIoutput {voidWrite (stringcontent); } //This implementation of the Ioutput interface//is actually how do we write to the Console. Technically//we could also implement Ioutput to write to Debug//or Trace ... or anywhere else. Public classConsoleoutput:ioutput { Public voidWrite (stringcontent) {Console.WriteLine (content); } } //This interface decouples the notion of writing//a date from the actual mechanism that performs//The writing. Like with Ioutput, the process//Is abstracted behind an interface. Public InterfaceIdatewriter {voidwritedate (); } //This todaywriter are where it all comes together. //Notice It takes a constructor parameter of type//Ioutput-that lets the writer write to anywhere//based on the implementation. Further, it implements//Writedate such that today's date is written out; //You could has one, writes in a different format//or a different date. Public classTodaywriter:idatewriter {PrivateIoutput _output; Publictodaywriter (ioutput output) { This. _output =output; } Public voidwritedate () { This. _output. Write (DateTime.Today.ToShortDateString ()); } }}
Add AUTOFAC Reference
First add the AUTOFAC reference to your project, in this case we add only AUTOFAC core references, and other types of applications may use different Autofac.integration class libraries.
With NuGet you can easily introduce references to projects,
App startup (application startup)
In??? At startup, you need to create a containerbuilder and use it to register various components. A component can be an expression, a. NET type or some code used to expose internal services.
In a nutshell, there is a type that implements the interface, as follows:
Public class sometype:iservice{}
You can navigate to it in two ways: by Type SomeType, or by Interface IService.
In this example, the component is sometype, while the exposed service refers to the SomeType type and the IService interface.
In AUTOFAC, you should register them by Containerbuilder.
// Create your builder. var New Containerbuilder (); // usually you ' re only interested in exposing the type // via its interface:builder. Registertype<sometype> (). As<iservice>(); // However, if you want BOTH services (not as common) // You can say so:builder. Registertype<sometype> (). Asself (). As<iservice> ();
For our sample application, we need to register all of our components (classes) and expose their services (interfaces).
We also need to store the container so that it can then be used to parse out various types of instances.
usingSystem;usingAUTOFAC;namespacedemoapp{ Public classProgram {Private StaticIContainer Container {Get;Set; } Static voidMain (string[] args) { varBuilder =NewContainerbuilder (); Builder. Registertype<ConsoleOutput> (). As<ioutput>(); Builder. Registertype<TodayWriter> (). As<idatewriter>(); Container=Builder. Build (); //The Writedate method is where we 'll make a use//of our dependency injection. We ' ll define that//In a bit.writedate (); } }}
So we have a container that registers all the components that expose their services at the same time. Now let's use this container.
Application Run time
During application runs, you need to resolve component instances from the container lifecycle domain to use them. The container itself is a lifecycle domain (lifetime scope), and technically you can parse the required components directly from the container.
However, we do not recommend directly manipulating containers, which can lead to memory leaks.
When we parse out a component, we rely on our defined lifetime scope, and a new object instance is created. Some of these components may need to be freed, such as objects that implement the IDispose interface. When the lifecycle domain is freed, AUTOFAC can automatically handle the release of component resources.
However, the container exists throughout the application life cycle. If you parse a large number of components directly from the container, it can cause many components to wait to be released. This is not a good practice and usually leads to memory leaks.
The alternative is that each time we create a sub-life cycle domain from the container. When you finish parsing the component from the subdomain, the subdomain will be freed, and all resources will be cleaned out.
For our sample program, we will parse out the Idatewriter instance from the subdomain and run the Writerdate () method. At the same time, when we are done, the subdomain will be released.
namespacedemoapp{ Public classProgram {Private StaticIContainer Container {Get;Set; } Static voidMain (string[] args) { //... the stuff you saw earlier ... } Public Static voidwritedate () {//Create The scope, resolve your idatewriter,//Use it, then dispose of the scope. using(varScope =Container.beginlifetimescope ()) { varwriter = scope. Resolve<idatewriter>(); Writer. Writedate (); } } }}
Now when you run your program ...
- The Writedate () method requests the Idatewriter instance from the AUTOFAC.
- Autofac discovers that Idatewriter can be mapped to the Todaywriter type, so a Todaywriter instance is created .
- Autofac found that Todaywriter needed a ioutput instance in its constructor .
- Autofac discovers that ioutput can be mapped to consoleoutput, so a new Consoleoutput instance is created.
- AUTOFAC Constructs a Todaywriter instance using the consoleoutput instance .
- AUTOFAC returns a fully constructed Todaywriter instance for use with the "Writedate" method.
After that, if your program wants to implement a different date for the output, you can construct different implementations of the Idatewriter interface and register it at the start of the app. You don't have to change any of the other classes. That's control reversal!
Note: Normally service location is considered anti-pattern to a large extent. In other words, creating a domain (scope) and using a large number of containers everywhere is not necessarily the best scenario. With AUTOFAC you don't usually have to do what we do in the sample app. Components are parsed from the center or top level of an application, and handwritten solutions are rare. Of course, it's up to you to design your application.
. NET notes-autofac Getting started getting Started