1. Introduction
Unity's life cycle is the life cycle of registered types of objects, and unity automatically helps us maintain the life cycle of those objects by default, and we can also display the lifecycle of the configuration objects, and unity will be automatically managed according to the configuration, which is very convenient, as described below The life cycle manager built into unity. 2.Lifetime managers life cycle management
Prepare the following class relationships to demonstrate
There are 2 interface classes: IClass (class Interface) and Isubject (account interface), each of which has 2 implementation classes. Take a look at the following example
public static void RegisterInstance ()
{
IClass myClass = new MyClass ();
IClass YourClass = new YourClass ();
Registers the default instance container for the MyClass instance
. Registerinstance<iclass> (myClass);
Registers a named instance with the Registertype container for the YourClass instance
. Registerinstance<iclass> ("Yourinstance", yourclass);
Container. Resolve<iclass> (). Showinfo ();
Container. Resolve<iclass> ("Yourinstance"). Showinfo ();
}
This code is simple to register an existing object through the RegisterInstance method, so that the life cycle of these object instances can be managed through UnityContainer.
It is important to note that registerinstance is used to register an existing instance with the UnityContainer, which by default is ContainerControlledLifetimeManager, the life cycle is managed by UnityContainer, UnityContainer maintains a strong reference to an object instance, and when you register an existing instance with UnityContainer, each time you get the object through the Resolve method is the same object. That is, a single instance (singleton instance), specific information about the life cycle is described below.
Because RegisterInstance is registered with an existing instance, it cannot be configured through a configuration file. Additional overloads for the RegisterInstance method I will not go into detail here, you can click here to see a detailed description of the overloaded method.
The following details the life cycle management of each Unity 2.1 Transientlifetimemanager
Transient life cycle, by default, when using Registertype for object Relational registration, if no lifecycle Manager is specified, the life cycle Manager is used by default, and the Lifecycle Manager is the same as its name, and when the manager is used, A new object is recreated every time the object is called through resolve or ResolveAll.
It is important to note that this life cycle cannot be specified when a relationship is registered with an existing object using RegisterInstance, otherwise an exception is reported.
The code is as follows:
public static void Transientlifetimemanagercode ()
{
//The following 2 kinds of registration effects are the same
container. Registertype<iclass, myclass> ();
Container. Registertype<iclass, myclass> (New Transientlifetimemanager ());
Console.WriteLine ("-------Transientlifetimemanager Begin------");
Console.WriteLine ("First Call Registertype registered object hashcode:" +
container. Resolve<iclass> (). GetHashCode ());
Console.WriteLine ("The second call to Registertype registered object hashcode:" +
container. Resolve<iclass> (). GetHashCode ());
Console.WriteLine ("-------Transientlifetimemanager End------");
}
The configuration file is as follows:
<register type= "IClass" mapto= "MyClass" >
<lifetime type= "transient"/>
<!--<lifetime Type= "Sessionlifetimemanager"
value= "session#1" typeconverter= "
sessionlifetimeconverter"/>--> </register>
If you want to change a lifecycle manager in the configuration file at the time of registering the relationship, simply add the <lifetime> in the <register> configuration section (the default is to use Transientlifetimemanager if not added).
where <lifetime> has 3 parameters:
1) type, life cycle manager types, this way you can choose unity built-in, or you can use custom, where the built-in life cycle Manager will have smart hints.
2) TypeConverter, life cycle Manager conversion class, a converter is created when a user customizes a lifecycle manager.
3) value, initializes the values of the life cycle manager.
Config file read code:
public static void Transientlifetimemanagerconfiguration ()
{
//Gets the configuration section for the specified name
unityconfigurationsection Section = (unityconfigurationsection) configurationmanager.getsection ("Unity");
Container. Loadconfiguration (section, "First");
Console.WriteLine ("-------Transientlifetimemanager Begin------");
Console.WriteLine ("First Call Registertype registered object hashcode:" +
container. Resolve<iclass> ("transient"). GetHashCode ());
Console.WriteLine ("The second call to Registertype registered object hashcode:" +
container. Resolve<iclass> ("transient"). GetHashCode ());
Console.WriteLine ("-------Transientlifetimemanager End------");
}
The results are as follows, and you can see that each of the resulting objects is different:
2.2 ContainerControlledLifetimeManager
Container control lifecycle management, which is the lifecycle manager used by the registerinstance by default, which is a single instance, UnityContainer maintains a strong reference to an object instance, returning the same object each time it is called, with the sample code as follows:
public static void Containercontrolledlifetimemanagercode () {IClass myClass = new MyClass (); The following 2 registration effects are the same container.
Registerinstance<iclass> ("CCL", myClass); Container.
Registerinstance<iclass> ("CCL", MyClass, New ContainerControlledLifetimeManager ()); Container.
Registertype<iclass, myclass> (New ContainerControlledLifetimeManager ());
Console.WriteLine ("-------ContainerControlledLifetimeManager Begin------"); Console.WriteLine ("First Call Registertype registered object hashcode:" + container. Resolve<iclass> ().
GetHashCode ()); Console.WriteLine ("The second call to Registertype registered object hashcode:" + container. Resolve<iclass> ().
GetHashCode ()); Console.WriteLine ("First Call RegisterInstance registered object hashcode:" + container. Resolve<iclass> ("CCL").
GetHashCode ()); Console.WriteLine ("The second call to RegisterInstance registered object hashcode:" + container. Resolve<iclass> ("CCL").
GetHashCode ()); Console.WriteLine ("-------ContainercontrolledlifetimemanaGER End------"); }
The configuration file is as follows:
<register type= "IClass" mapto= "MyClass" name= "CCL" >
<lifetime type= "singleton"/>
</register >
The renderings are as follows, and you can see that each object you get is the same object:
2.3 Hierarchicallifetimemanager
Hierarchical lifecycle Manager, a manager similar to ContainerControlledLifetimeManager, is also managed by UnityContainer, which is a single instance. Unlike ContainerControlledLifetimeManager, however, this lifecycle manager is layered because the container of unity can be nested, so this lifecycle manager is for this case, when this lifecycle manager is used, the parent container And the life cycle of the objects maintained by the sub-containers are managed by the respective containers, and the code is as follows (the registerinstance situation is similar, not shown here)
public static void Hierarchicallifetimemanagercode ()
{
container. Registertype<iclass, myclass> (New Hierarchicallifetimemanager ());
Create a child container
var childcontainer = container. Createchildcontainer ();
Childcontainer.registertype<iclass, myclass> (New Hierarchicallifetimemanager ());
Console.WriteLine ("-------ContainerControlledLifetimeManager Begin------");
Console.WriteLine ("First call the parent container registered object hashcode:" +
container. Resolve<iclass> (). GetHashCode ());
Console.WriteLine ("The second call to the parent container registered object hashcode:" +
container. Resolve<iclass> (). GetHashCode ());
Console.WriteLine ("First call the sub-container registered object hashcode:" +
childcontainer.resolve<iclass> (). GetHashCode ());
Console.WriteLine ("The second call to the sub-container registered object hashcode:" +
childcontainer.resolve<iclass> (). GetHashCode ());
Console.WriteLine ("-------ContainerControlledLifetimeManager End------");
}
Because the configuration file cannot be configured with this level of effect, you only need to change the following lifecycle name when configuring this life cycle:
<register type= "IClass" mapto= "MyClass" name= "HL" >
<lifetime type= "Hierarchical"/>
</ Register>
The specific renderings are as follows, and you can see that the parent and child maintain different object instances:
Here's what you need to mention is that the benefit of unity's tiered containers is that we can place objects with different lifecycles in different containers, and if a child container is freed, it will not affect objects in other sub-containers, but if the parent container at the root node is freed, all child containers will be freed. 2.4 Perresolvelifetimemanager
This life cycle is to resolve circular references and repeat the reference life cycle, first look at Microsoft's official example:
Public interface IPresenter
{} public
class Mockpresenter:ipresenter
{public
IView View {get; set;} Public
Mockpresenter (IView view)
{
view = view;
}
}
Public interface IView
{
IPresenter Presenter {get; set;}
}
public class View:iview
{
[Dependency] public
IPresenter Presenter {get; set;}
}
From this example, it can be seen that there are 2 interfaces Ipresenter and iview, there are 2 classes Mockpresenter and view to implement these 2 interfaces, while the 2 classes contain the object properties of another class, this is a circular reference, The corresponding lifecycle management is new to this case, similar to Transientlifetimemanager, but the difference is that if this lifecycle manager is applied, a new object is created when the first call is made, and the When the circular reference is accessed, the previously created object instance (single instance) is returned with the following code:
public static void Perresolvelifetimemanagercode () {var container = new UnityContainer (). Registertype<ipresenter, Mockpresenter> ().
Registertype<iview, view> (New Perresolvelifetimemanager ()); var view = container.
Resolve<iview> (); var temppresenter = container.
Resolve<ipresenter> (); var realpresenter = (mockpresenter) view.
Presenter;
Console.WriteLine ("-------Perresolvelifetimemanager Begin------");
Console.WriteLine ("Objects using Perresolvelifetimemanager Begin"); Console.WriteLine ("View object obtained by the Resolve method:" + view.)
GetHashCode ());
Console.WriteLine (The View object contained in the presenter object in the View object: "+ RealPresenter.View.GetHashCode ());
Console.WriteLine ("Object End with Perresolvelifetimemanager");
Console.WriteLine ("");
Console.WriteLine ("Objects not using Perresolvelifetimemanager Begin");
Console.WriteLine ("Presenter object in the View object:" + Realpresenter.gethashcode ()); Console.WriteLine ("View object obtained by the Resolve method:" + TemppreSenter.
GetHashCode ());
Console.WriteLine ("Object End not using Perresolvelifetimemanager");
Console.WriteLine ("-------Perresolvelifetimemanager Begin------"); }
As can be seen from the code, when registering an object, only Perresolvelifetimemanager is applied to iview and view, so the second access to the View object returns the same instance.
Specific configuration files are described in the next article for constructor injection and attribute injection :
<alias alias= "IPresenter" type= "Unitystudyconsole.ipresenter, unitystudyconsole"/> <alias alias=
" IView "Type=" Unitystudyconsole.iview, unitystudyconsole "/>
<alias alias=" Mockpresenter "type=" Unitystudyconsole.mockpresenter, Unitystudyconsole "/>
<alias alias=" View "type=" Unitystudyconsole.view, Unitystudyconsole "/>
<container name=" Second ">
<register type=" IPresenter "mapto=" Mockpresenter ">
<constructor>
<param name =" View "type=" IView ">
</param>
</constructor>
</register>
<register type= "IView" mapto= "View" >
<lifetime Type= "Perresolve"/>
<property name= "Presenter" dependencytype= "IPresenter" ></property>
</register>
</container>
Reading the configuration file code is similar to the previous other configuration file read code, which is not shown here, see the sample code for details.
The specific effect diagram is as follows:
You can see that the hashcode of 2 calls to the View object are the same, and the hashcode of the presenter object is different. 2.5 Perthreadlifetimemanager
Per-thread life cycle Manager, is to ensure that each thread returns the same instance, the code is as follows:
public static void Perthreadlifetimemanagercode () {container.
Registertype<iclass, myclass> (New Perthreadlifetimemanager ());
var thread = new Thread (new Parameterizedthreadstart (THREAD1));
Console.WriteLine ("-------Perresolvelifetimemanager Begin------");
Console.WriteLine ("Default thread Begin"); Console.WriteLine ("First Call:" + container. Resolve<iclass> ().
GetHashCode ()); Console.WriteLine ("Second Call:" + container. Resolve<iclass> ().
GetHashCode ());
Console.WriteLine ("Default thread End"); Thread.
Start (container);
} public static void Thread1 (Object obj) {var tmpcontainer = obj as UnityContainer;
Console.WriteLine ("New Thread Begin"); Console.WriteLine ("First Call:" + tmpcontainer.resolve<iclass> ().
GetHashCode ()); Console.WriteLine ("Second call:" + tmpcontainer.resolve<iclass> ().
GetHashCode ());
Console.WriteLine ("New Thread End");
Console.WriteLine ("-------Perresolvelifetimemanager End------"); }
For configuration-related code similar to the previous life cycle manager, there is no code on this side, see the sample code.
The specific effect diagram is as follows:
It is also important to note that it is generally not recommended to use Perthreadlifetimemanager when using registerinstance to register relationships with existing objects, because objects are already created in a line range. If you use this lifecycle manager again, there is no guarantee that it will be called correctly. 2.6 Externallycontrolledlifetimemanager
The external control life cycle Manager, which allows you to use Registertype and registerinstance to register relationships between objects, but only retains a weak reference to the object whose life cycle is controlled externally, This means that you can cache or destroy the object without worrying about the unitycontainer, and when the object is not strongly referenced elsewhere, it will be destroyed by the GC.
By default, using this lifecycle manager, each call to resolve will return the same object (a single instance), and if the Resolve method is called again after being reclaimed by GC, the new object will be recreated with the sample code as follows:
public static void Externallycontrolledlifetimemanagercode ()
{
container. Registertype<iclass, myclass> (New Externallycontrolledlifetimemanager ());
var myClass1 = container. Resolve<iclass> ();
var myClass2 = container. Resolve<iclass> ();
Console.WriteLine ("-------Externallycontrolledlifetimemanager Begin------");
Console.WriteLine ("First Call:" +
Myclass1.gethashcode ());
Console.WriteLine ("Second call:" +
Myclass2.gethashcode ());
MyClass1 = MyClass2 = null;
Gc. Collect ();
Console.WriteLine ("****GC after Recovery");
Console.WriteLine ("First Call:" +
container. Resolve<iclass> (). GetHashCode ());
Console.WriteLine ("Second call:" +
container. Resolve<iclass> (). GetHashCode ());
Console.WriteLine ("-------Externallycontrolledlifetimemanager End------");
}
For configuration-related code similar to the previous life cycle manager, there is no code on this side, see the sample code.
The effect diagram is as follows:
3. Summary
Because they are learning unity, in the search for relevant information, found this in the garden, looked at a bit is very good, so reproduced the