Starting from the Global.asax file, analyze the NOP architecture layer by level.
The Application_Start () method is the first method initiated by MVC.
1, first initialize an engine context, such as the following code: Enginecontext.initialize (FALSE);
The engine implements the Iengine interface, which is defined as follows:
public interface Iengine
{
Containermanager Containermanager {get;}
void Initialize (Nopconfig config);
T resolve<t> () where t:class;
Object Resolve (type type);
T[] resolveall<t> ();
}
2, the following work is done specifically in the Enginecontext.initialize (false) method:
The first is singleton<iengine>. Instance = = null judgment, Singleton<iengine>. Instance is a generic singleton pattern, defined as follows:singleton<t>: Singleton, which defines a idictionary<type, object> collection in Singleton, Each time a value is assigned to instance, it is saved to the collection and cached to the entire application.
3, this line code is exactly the assignment to the instance: Singleton<iengine>. Instance = createengineinstance (config)
Next analyze how Createengineinstance (config) gets to an instance of the engine:
(1) Parameter config is an example of nopconfig, which is better understood by reading the information of node Nopconfig in Web. config.
(2) Enginetype This value in the configuration file is "", so it instantiates a default engine: Nopengine.
(3) When instantiating the Nopengine engine, the public nopengine (Eventbroker broker, Containerconfigurer Configurer) constructor is called.
Parameter type broker=eventbroker.instance; An event Registration class during an HTTP request, which is primarily an event during an HTTP request.
Configurer=new Containerconfigurer (); Instantiate a Configuration service NOP using control reversal container
(4) eventbroker.instance parameter analysis: Through this way: singleton<eventbroker>. Instance gets a Eventbroker instance.
4, by constructing the above three parameters, the program starts executing initializecontainer (configurer, Broker, config), this process is dependency injection, utilizing the AUTOFAC third-party class library.
Code Analysis:
(1) var builder = new Containerbuilder (); Create a dependency Injection container constructor, and all the injections are done by it.
(2) _containermanager = new Containermanager (builder. Build ()); Builder. Build () Autofac to create a container and pass the container to the constructor of the NOP custom container management class. Containermanager manages the various situations in which the injection method is administered.
(3) Next Call Configurer. Configure (this, _containermanager, Broker, config), the method is to configure the dependency injection core in which to inject all the application's needs into batches.
A: Inject a few global configurations, the following code,
Containermanager.addcomponentinstance<nopconfig> (Configuration, "nop.configuration");
Containermanager.addcomponentinstance<iengine> (Engine, "nop.engine");
Containermanager.addcomponentinstance<containerconfigurer> (This, "nop.containerconfigurer");
To specifically analyze containermanager.addcomponentinstance<iengine> (engine, "nop.engine"); What does the line code do primarily?
The signature of the Calling method is Addcomponentinstance<tservice> (object instance, string key = "", Componentlifestyle LifeStyle = Componentlifestyle.singleton)
Parameter description: instance: the instance name, which is the instance that needs to be injected, is an object type, which means that all types can be passed in.
Key: The name of the keyed value injected,
LifeStyle: The life cycle of an instance in a container, which is configured for Singleton, means that there is only one instance of the entire application life cycle.
Next Call Updatecontainer (x =
{
var registration = x.registerinstance (instance). Keyed (key, service). As (service). Perlifestyle (LifeStyle);
}); The Updatecontainer method passes a action<containerbuilder> delegate.
X.registerinstance (instance). Keyed (key, service). As (service). Perlifestyle (lifeStyle); This line of code is a really injected process.
To update the container after registration, such as the following code:
Builder. Update (_container);
B: Register a Containermanager.addcomponent<itypefinder, webapptypefinder> ("Nop.typefinder"); The role of the Webapptypefinder class is to reflect what we want to inject through the assembly. The method calls AddComponent (typeof (TService), typeof (Timplementation), key, LifeStyle);
and then call
Updatecontainer (x =
{
var servicetypes = new List<type> {service}; Put the interface into a collection of list<type>.
if (service. Isgenerictype)//If it is a generic interface, do the following.
{
var temp = X.registergeneric (Implementation). As (
Servicetypes.toarray ()). Perlifestyle (LifeStyle);
if (!string. IsNullOrEmpty (Key))
{
Temp. Keyed (key, service);
}
}
else//is not a generic interface, do the following.
{
var temp = X.registertype (Implementation). As (
Servicetypes.toarray ()). Perlifestyle (LifeStyle);
if (!string. IsNullOrEmpty (Key))
{
Temp. Keyed (key, service); The key value is associated with the list<type>.
}
}
});
C: Next we'll start with the class we just injected into the container. The code is the method called:
var typeFinder = containermanager.resolve<itypefinder> ();
Code Analysis: Resolve
Public T resolve<t> (string key = "") where T:class
{
if (string. IsNullOrEmpty (key))//key the value is empty. The following method is called.
{
Return Scope (). Resolve<t> ();
}
Return Scope (). Resolvekeyed<t> (key);
}
D: Analyze scope (). The Resolve<t> () method is an instance of how to get from a container.
public Ilifetimescope Scope () //Get a container life cycle range.
{
try
{
return Autofacrequestlifetimehttpmodule.getlifetimescope (Container, null); //
}
catch
{
return Container;
}
}
Method Autofacrequestlifetimehttpmodule.getlifetimescope (Container, NULL) is as follows:
public static Ilifetimescope Getlifetimescope (Ilifetimescope container, action<containerbuilder> Configurationaction)
{
Little hack here-get dependencies when HttpContext are not available
if (httpcontext.current! = null)
{
Return lifetimescope?? (Lifetimescope = Initializelifetimescope (configurationaction, container));
}
Else
{
throw new InvalidOperationException ("httpcontextnotavailable");
Return Initializelifetimescope (configurationaction, container);
}
}
The last program returns an instance of the Ilifetimescope interface. Interface Inheritance Relationship: Ilifetimescope:icomponentcontext
Call the interface's Resolve<t> () method to return the true object.
Method implementation code: Icomponentcontext extension method.
public static TService resolve<tservice> (this icomponentcontext context)
{
Return resolve<tservice> (context, noparameters);
}
The instance is then fetched from the container.
NOP Source Code Analysis One