Article From:https://www.cnblogs.com/bincoding/p/9060420.html

1.Introduction

UnityThe lifecycle is the life cycle of the registered type object, and Unity automatically helps us maintain the lifecycle of these objects by default, and we can also display the lifecycle of the configuration objects, and Unity will be managed automatically, very convenient, and the following is the introduction to the UnityThe built-in lifecycle manager.

2.Lifetime ManagersLife cycle management

Prepare the following class relationships for demonstration

There are 2 interface classes: IClass (class interface) and ISubject (subject interface), which have 2 implementation classes respectively. Look at the following example

Copy code
public static void RegisterInstance(){    IClass myClass = new MyClass();    IClass yourClass = new YourClass();    //Register a default instance for a myClass instance    container.RegisterInstance<IClass>(myClass);    //Registration instance for yourClass instance, same as RegisterType    container.RegisterInstance<IClass>("yourInstance", yourClass);     container.Resolve<IClass>().ShowInfo();     container.Resolve<IClass>("yourInstance").ShowInfo();}
Copy code

The simple code is to register the existing objects through the RegisterInstance method so that the lifecycle of these object instances can be managed by UnityContainer.

It is important to note that the RegisterInstance is used to register the existing instances into the UnityContainer, which is actually used by default for ContainerControlledLifetimeManager.The lifecycle is managed by UnityContainer, and UnityContainer maintains a strong reference to an object instance, and when you register an existing instance to UnityContainer, every time you get the pair through the Resolve methodImage is the same object, that is, singleton instance, and the related life cycle related information is introduced below.

Because RegisterInstance is registering existing instances, it cannot be configured through configuration files. Other overloading of the RegisterInstance method is not detailed here. You can view the detailed overload method.

Next, we will introduce the lifecycle management of each Unity in detail.

2.1 TransientLifetimeManager

Transient life cycle, by default, in useRegisterTypeThe lifecycle manager is used by default if the lifecycle manager is not specified when the object relationship registers are registered, and the lifecycle manager is just like its name, and every time it is used, each time is passed.ResolveorResolveAllWhen you call the object, you re create a new object.

It should be noted that when RegisterInstance is used to register existing objects, it can not specify the life cycle, otherwise it will report exceptions.

The code is as follows:

Copy code
public static void TransientLifetimeManagerCode(){    //The following 2 Registration effects are the same    container.RegisterType<IClass, MyClass>();    container.RegisterType<IClass, MyClass>(new TransientLifetimeManager());    Console.WriteLine("-------TransientLifetimeManager Begin------");    Console.WriteLine("For the first time, the object registered by RegisterType is called HashCode:." +        container.Resolve<IClass>().GetHashCode());    Console.WriteLine("The second call to the object HashCode: registered by RegisterType" +        container.Resolve<IClass>().GetHashCode());    Console.WriteLine("-------TransientLifetimeManager End------");}
Copy code

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 during the registration relationship in the configuration file, only the < register> the configuration section is added to < lifetime> if not added, the TransientLifetime is used by default.Manager).

< lifetime> there are 3 parameters:

1)type,The type of life cycle manager, this side can choose Unity built-in, also can use custom, in which the built-in lifecycle manager will have intelligent hints.

2)typeConverter,Lifecycle Manager transforms classes to create a converter when users customize a lifecycle manager.

3)value,Initializes the value of the lifecycle manager.

Configuration file read code:

Copy code
public static void TransientLifetimeManagerConfiguration(){    //Get the configuration section of the specified name    UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");    container.LoadConfiguration(section, "First");     Console.WriteLine("-------TransientLifetimeManager Begin------");    Console.WriteLine("For the first time, the object registered by RegisterType is called HashCode:." +        container.Resolve<IClass>("transient").GetHashCode());    Console.WriteLine("The second call to the object HashCode: registered by RegisterType" +        container.Resolve<IClass>("transient").GetHashCode());    Console.WriteLine("-------TransientLifetimeManager End------");}
Copy code

The effect diagram is as follows: it can be seen that the objects produced each time are different.

pic72

 

2.2 ContainerControlledLifetimeManager

The container controls lifecycle management, the lifecycle manager that RegisterInstance uses by default, that is, a single instance, and UnityContainer maintains a strong reference to an object instance, and returns the same pair every time the call is made.The example code is as follows:

 

Copy code
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("For the first time, the object registered by RegisterType is called HashCode:." +        container.Resolve<IClass>().GetHashCode());    Console.WriteLine("The second call to the object HashCode: registered by RegisterType" +        container.Resolve<IClass>().GetHashCode());    Console.WriteLine("For the first time, the object registered by RegisterInstance is called HashCode:." +        container.Resolve<IClass>("ccl").GetHashCode());    Console.WriteLine("The second call to the object HashCode: registered by RegisterInstance" +        container.Resolve<IClass>("ccl").GetHashCode());    Console.WriteLine("-------ContainerControlledLifetimeManager End------");}
Copy code

The configuration file is as follows:

<register type="IClass" mapTo="MyClass" name="ccl">  <lifetime type="singleton" /></register>

The effect diagram is as follows: we can see that every object we get is the same object:

pic73

2.3 HierarchicalLifetimeManager

Layered lifecycle manager, this manager is similar toContainerControlledLifetimeManager,It is also managed by UnityContainer, that is, single instance. But withContainerControlledLifetimeManagerThe difference is that the lifecycle manager is layered because the Unity container can be nested, so this lifecycle manager is aimed at this case, when the lifecycle manager is used, the life cycle of the object maintained by the parent container and the child container is managed by the respective containers.The code is as follows (RegisterInstance is similar, and this is not displayed here).

Copy code
public static void HierarchicalLifetimeManagerCode(){    container.RegisterType<IClass, MyClass>(new HierarchicalLifetimeManager());    //Creating a subcontainer    var childContainer = container.CreateChildContainer();    childContainer.RegisterType<IClass, MyClass>(new HierarchicalLifetimeManager());     Console.WriteLine("-------ContainerControlledLifetimeManager Begin------");    Console.WriteLine("The first call to the object HashCode: of the parent container" +        container.Resolve<IClass>().GetHashCode());    Console.WriteLine("Second invocation of the object HashCode: registered with the parent container" +        container.Resolve<IClass>().GetHashCode());    Console.WriteLine("The first call to the object HashCode: of the child container registration" +        childContainer.Resolve<IClass>().GetHashCode());    Console.WriteLine("Second invocation of the object HashCode: of the child container" +        childContainer.Resolve<IClass>().GetHashCode());    Console.WriteLine("-------ContainerControlledLifetimeManager End------");}
Copy code

Because the configuration file can not configure this hierarchical effect, it is necessary to change the next lifecycle name when configuring this life cycle.

<register type="IClass" mapTo="MyClass" name="hl">  <lifetime type="hierarchical" /></register>

The specific effect diagram is as follows: we can see that parent class and child level maintain different object instances:

pic74

What needs to be mentioned here is that the advantage of Unity’s hierarchical container is that we can put in different containers for objects with different lifecycle. If a sub container is released, it does not affect the objects in other subcontainers, but if the parent container is released at the root node, all the subcontainers are released.All will be released.

2.4 PerResolveLifetimeManager

This lifecycle is a life cycle repeated to refer to circular references. Let’s take a look at the examples given by Microsoft official:

Copy code
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; }}
Copy code

As you can see from this example, there are 2 interfaces, IPresenter and IView, and 2 classes of MockPresenter and View to implement the 2 interfaces respectively, and both of the 2 classes contain the object attributes for another class, which is a circular referenceAnd the corresponding life cycle management is new to this situation, which is similar to TransientLifetimeManager, but the difference is that if the lifecycle manager is applied, a new object will be created at the time of the first call, and the other is to create a new object in the first call.When accessed by cyclic references, the object instance is previously returned.Single instance),The code is as follows:

Copy 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("The object Begin of PerResolveLifetimeManager is used");    Console.WriteLine("The View object obtained through the Resolve method:" +        view.GetHashCode());    Console.WriteLine("ViewThe View object contained in the Presenter object of the object:" +        realPresenter.View.GetHashCode());    Console.WriteLine("The object End of PerResolveLifetimeManager is used");    Console.WriteLine("");    Console.WriteLine("Object Begin that does not use PerResolveLifetimeManager");    Console.WriteLine("ViewThe Presenter object in the object:" +        realPresenter.GetHashCode());    Console.WriteLine("The View object obtained through the Resolve method:" +        tempPresenter.GetHashCode());    Console.WriteLine("Object End that does not use PerResolveLifetimeManager");    Console.WriteLine("-------PerResolveLifetimeManager Begin------");}
Copy code

As you can see from the code, when the object is registered, only the PerResolveLifetimeManager is applied to IView and View, so the second access to the View object will return the same instance.

The specific configuration file is as follows.The content of constructor injection and attribute injection is introduced in the next article.

Copy code
<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>
Copy code

Reading the configuration file code is similar to reading the other configuration files in the front. This is not shown here. Let’s look at the sample code.

The specific results are as follows:

pic75

It can be seen that the HashCode of the 2 calling View objects is the same, while the HashCode of the Presenter object is different.

2.5 PerThreadLifetimeManager

Each thread lifecycle manager is to ensure that each thread returns the same instance. The specific code is as follows:

Copy code
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 calls:" +        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 calls:" +        tmpContainer.Resolve<IClass>().GetHashCode());    Console.WriteLine("New thread End");Console.WriteLine("-------PerResolveLifetimeManager End------"); }
Copy code

The configuration related code is almost the same as the previous lifecycle manager. Here is no code. Please look at the sample code.

The specific results are as follows:

pic76

It is also important to note that, in general, it is not recommended to use the PerThreadLifetimeManager when using the RegisterInstance to register the existing object relationship, because the object is already created in one thread, if this is used again.Life cycle manager will not guarantee its correct call.

 

2.6 ExternallyControlledLifetimeManager

External control life cycle manager, which allows you to register relationships between objects using RegisterType and RegisterInstance, but it only holds a weak reference to the object, and its lifecycle is externally controlled, that is, meaningYou can cache or destroy this object without caring about UnityContainer, and when other places do not have a strong reference to the object, it will be destroyed by the GC.

By default, using this lifecycle manager, every call to the Resolve returns the same object (a single instance), and a new Resolve method will be recreated if the GC is reclaimed after being reclaimed, and the example code is as follows:

Copy code
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("The first call:" +        myClass1.GetHashCode());    Console.WriteLine("The second call:" +        myClass2.GetHashCode());    myClass1 = myClass2 = null;    GC.Collect();    Console.WriteLine("****GCAfter recovery * * * * *");    Console.WriteLine("The first call:" +       container.Resolve<IClass>().GetHashCode());    Console.WriteLine("The second call:" +       container.Resolve<IClass>().GetHashCode());     Console.WriteLine("-------ExternallyControlledLifetimeManager End------");}
Copy code

The configuration related code is almost the same as the previous lifecycle manager. Here is no code. Please look at the sample code.

The results are as follows:

pic77

 

3.Summary

Since I was learning Unity, looking up the relevant information and finding this in the garden, it was very nice to see it, so it was reproduced. The text link: http://www.cnblogs.com/kyo-yo/archive/2010/11/10/Learning-EntLib-Tenth-Decoupling-Your-System-Using-The-Unity-PART2-Learn-To-Use-Unity-Two.html, the text in it.The book is well written, and you can check it.

 

  • Author: Qlin
  • Source: http://www.cnblogs.com/qqlin/
  • The copyright of this article is shared by the author and the blogger. It is welcome to reprint, but the statement must be retained without the consent of the author, and the original connection is given in the obvious position of the article page, otherwise the right to be investigated for legal responsibility is retained.

Similar Posts:

Leave a Reply

Your email address will not be published. Required fields are marked *