In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces "how to use Unity to achieve IOC in C#". In daily operation, I believe many people have doubts about how to use Unity to achieve IOC in C#. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts about how to use Unity to achieve IOC in C#! Next, please follow the editor to study!
What is IOC
Before learning IOC, let's learn about a dependency-led principle (DIP), which is the core principle of IOC.
Dependency leads to: that is, the upper module should not rely on the lower module, the two should be depended on through abstraction. Rely on abstraction, not on detail.
First, let's take a look at the following example:
1. Define an API to encapsulate the basic CRUD operation of the database. The definition of the API is as follows:
Using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Data;namespace DataBase.Interface {/ data access interface / public interface IDbInterface {string Insert (); string Delete (); string Update (); string Query ();}}
2. Define a MSSQL class to implement the interface, which is used to simulate SQLServer operations. The MSSQL class is defined as follows:
Using DataBase.Interface;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.MSSQL {public class DbMSSQL: IDbInterface {public string Delete () {return "MSSQL perform delete";} public string Insert () {return "MSSQL perform insert" } public string Query () {return "MSSQL execute query";} public string Update () {return "MSSQL execute Update";}
3. Define an Oracle class to implement the interface, imitating the operation of Oracle. The Oracle class is defined as follows:
Using DataBase.Interface;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.Oracle {public class DbOracle: IDbInterface {public string Delete () {return "Oracle perform delete";} public string Insert () {return "Oracle perform insert" } public string Query () {return "Oracle execute query";} public string Update () {return "Oracle execute Update";}
4. Define a console application to call:
Using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using DataBase.Interface;using DataBase.MSSQL;namespace IOCConApp {class Program {static void Main (string [] args) {/ / General practice, that is, the upper end of the program depends on the lower end, depending on the details DbMSSQL mssql = new DbMSSQL ();}
The general practice is to add a reference and then instantiate the class directly, but this depends on the detailed implementation, so the code is modified as follows:
/ / rely on IDbInterface dbInterface = new DbMSSQL () through abstraction
But after this modification, although the left side is abstract, the right side still depends on the details.
So what on earth is IOC?
IOC (Inversion of Control), namely control inversion, is an important object-oriented programming rule to reduce the coupling problem between programs and transfer the dependence of the upper and middle layers of the program on the lower layer to a third-party container for assembly. IOC is the goal of programming, which includes dependency injection and dependency lookup, and there is only dependency injection in. Net.
When it comes to IOC, we have to talk about DI. DI, that is, dependency injection, is the implementation means of IOC.
Second, use Unity to realize IOC
Unity is an IoC container used to implement dependency injection (Dependency Injection,DI), reduced coupling, Unity from the great Microsoft.
What can unity do? the list is as follows:
1.Unity supports simple object creation, especially hierarchical object structures and dependencies, to simplify program code. It contains a mechanism for compiling object instances that may be dependent on other objects.
2.Unity supports the necessary abstraction, which allows developers to specify dependencies at runtime or configuration while simply managing crosscutting points (AOP).
3.Unity increases the flexibility to defer configuration to container components. It also supports a container-level structure.
4.Unity has the ability to locate services, which is useful for a program to reuse components in many cases to separate and centralize functions.
5.Unity allows clients to store or cache containers. It is especially effective for developers in ASP.NET Web applications to persist containers in session or application in ASP.NET.
6.Unity has the ability to intercept, which allows developers to add a function to an existing component by creating and executing a handlers (before the method or property is called), and to return the result again.
7.Unity can read configuration information from the standard configuration system, such as the XML file, and use the configuration file to configure the container.
8.Unity allows developers to implement custom container extensions, for example, you can implement methods to allow additional object construction and container features, such as caching.
9.Unity allows architects and developers to implement common design patterns more easily in modern programs.
Under what circumstances should I use unity?
1. The system built depends on sound object-oriented principles, but a large number of different codes are intertwined and difficult to maintain.
two。 The objects and classes you build depend on other objects or classes.
3. Depends on objects that are complex or require abstraction.
4. You want to take advantage of the call injection of a constructor, method, or property.
5. You want to manage the lifecycle of an object instance.
6. You want to be able to manage and change dependencies at run time.
7. You want to generate a policy chain or pipeline processing container to implement the AOP task when intercepting method or property calls.
8. You want to be able to cache or persist dependencies during postback operations in Web Application.
1. Install Unity in the program
Use the manage NuGet package to install Unity, right-click the project, and select manage NuGet package:
Type Unity in the search box and click the install button on the right to install:
The following message indicates that the installation was successful:
2. Use Unity to implement DI
Let's first take a look at the simplest implementation of Unity:
IUnityContainer container = new UnityContainer (); / / 1, define an empty container container.RegisterType (); / / 2, register the type that encounters IDbInterface, create an instance of DbMSSQL var db = container.Resolve (); Console.WriteLine (db.Insert ()); Console.ReadKey ()
Results:
As you can see from the results, db is an instance of the DbMSSQL type.
In addition to registering a type using RegisterType, you can also register an instance, such as:
/ / use RegisterInstance to register IDbInterface instances: new DbMSSQL () container.RegisterInstance (new DbMSSQL ()); 3. Three injection methods
There are three injection methods: constructor injection, attribute injection and method injection.
Define the IHeadphone interface as follows: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.Interface {public interface IHeadphone {}} 3.2 defines the IMicrophone interface as follows: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks Namespace DataBase.Interface {public interface IMicrophone {}} 3.3 defines the IPower interface as follows: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.Interface {public interface IPower {}} 3.4 defines the IPhone interface as follows: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks Namespace DataBase.Interface {public interface IPhone {void Call (); IMicrophone iMicrophone {get; set;} IHeadphone iHeadphone {get; set;} IPower iPower {get; set;}} 3.5 respectively implement the interfaces defined above
The implementation of the IPhone interface is as follows:
Using DataBase.Interface;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Unity.Attributes;namespace DataBase.MSSQL {public class ApplePhone: IPhone {[Dependency] / / attribute injection public IMicrophone iMicrophone {get; set;} public IHeadphone iHeadphone {get; set;} public IPower iPower {get; set } [InjectionConstructor] / / Constructor injects public ApplePhone (IHeadphone headphone) {this.iHeadphone = headphone; Console.WriteLine ("{0} constructor with parameters", this.GetType () .Name);} public void Call () {Console.WriteLine ("{0} call", this.GetType () .Name); } [InjectionMethod] / / method injects public void Init1234 (IPower power) {this.iPower = power;}
The implementation of the IHeadphone interface is as follows:
Using DataBase.Interface;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.MSSQL {public class Headphone: IHeadphone {public Headphone () {Console.WriteLine ("Headphone is constructed");}
The implementation of the IMicrophone interface is as follows:
Using DataBase.Interface;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.MSSQL {public class Microphone: IMicrophone {public Microphone () {Console.WriteLine ("Microphone is constructed");}
The implementation of the IPower interface is as follows:
Using DataBase.Interface;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DataBase.MSSQL {public class Power: IPower {public Power () {Console.WriteLine ("Power is constructed");}
The console program calls:
Using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using DataBase.Interface;using DataBase.MSSQL;using Unity Namespace IOCConApp {/ IOC (): control reversal, transferring the dependence of the upper layer on the lower layer to a third-party container to assemble / / is the goal of programming. The way of implementation includes dependency injection and dependency lookup (.net there is only dependency injection) / DI: dependency injection is the internship way of IOC. / / class Program {static void Main (string [] args) {# region MyRegion / General practice, that is, the upper end of the program depends on the lower end, depends on the details / / DbMSSQL mssql = new DbMSSQL (); / depends on / / IDbInterface dbInterface = new DbMSSQL () through abstraction / / IUnityContainer container = new UnityContainer (); / / 1, define an empty container / / container.RegisterType (); / / 2, register the type that encounters IDbInterface, create an instance of DbMSSQL / / var db = container.Resolve (); / register an instance of IDbInterface using RegisterInstance: new DbMSSQL () / / container.RegisterInstance (new DbMSSQL ()) / / Console.WriteLine (db.Insert ()); # endregion IUnityContainer container = new UnityContainer (); container.RegisterType (); IPhone phone= container.Resolve (); Console.WriteLine ($"phone.iHeadphone==null? {phone.iHeadphone==null}") Console.WriteLine ($"phone.iMicrophone==null? {phone.iMicrophone==null}"); Console.WriteLine ($"phone.iPower==null? {phone.iPower==null}"); Console.ReadKey ();}
Output result:
From the output results, we can see the execution order of the three injection modes: first execute the constructor injection, then perform the attribute injection, and finally execute the method injection.
Note: by default, if no attributes are used on the constructor, the constructor with the most arguments is found by default to perform injection.
4. Register with multiple implementations of one interface
How can this be registered if multiple different instances implement the same interface? Let's take a look at the following code:
IUnityContainer container = new UnityContainer (); / / 1. Define an empty container container.RegisterType (); / / 2, register the type that encounters IDbInterface, create an instance of DbMSSQL container.RegisterType (); / / indicate that you encounter a type of IDbInterface, create an instance of DbMSSQL var db = container.Resolve (); Console.WriteLine (db.Insert ())
Running result:
As can be seen from the running results, the later registered types will overwrite the previously registered types, so how to solve the problem? It can be solved by parameters. The code is as follows:
IUnityContainer container = new UnityContainer (); / / 1. Define an empty container container.RegisterType ("sql"); / / 2, register the type that encounters IDbInterface, create an instance of DbMSSQL ("oracle"); / / indicate that the type that encounters IDbInterface, create an instance of DbMSSQL var sql = container.Resolve ("sql"); var oracle = container.Resolve ("oracle"); Console.WriteLine (sql.Insert ()); Console.WriteLine (oracle.Insert ())
Running result:
5. Life cycle
The life cycle and the time elapsed between creation and release of an object. Take a look at the following code first:
IUnityContainer container = new UnityContainer (); container.RegisterType (); IDbInterface db1 = container.Resolve (); IDbInterface db2 = container.Resolve (); Console.WriteLine ("HashCode:" + db1.GetHashCode (). ToString ()); Console.WriteLine ("HashCode:" + db2.GetHashCode (). ToString ()); Console.WriteLine (object.ReferenceEquals (db1,db2))
Results:
Indicates that db1 and db2 are two different instances, that is, the life cycle is instantaneous by default, and a new instance is created each time.
Container.RegisterType (new TransientLifetimeManager ()); indicates an instantaneous life cycle, which is the default.
Look at the following code:
IUnityContainer container = new UnityContainer (); container.RegisterType (new ContainerControlledLifetimeManager ()); IDbInterface db1 = container.Resolve (); IDbInterface db2 = container.Resolve (); Console.WriteLine ("HashCode:" + db1.GetHashCode (). ToString ()); Console.WriteLine ("HashCode:" + db2.GetHashCode (). ToString ()); Console.WriteLine (object.ReferenceEquals (db1, db2))
Results:
As you can see from the above figure, db1 and db2 are the same instance.
Container.RegisterType (new ContainerControlledLifetimeManager ()) indicates that it is a container singleton, with the same instance each time.
6. Use configuration files to implement
In the above example, all the examples rely on details all the time, so how to solve the problem without relying on details? The answer is that only configuration files can be used, which are as follows:
Note: this is a separate configuration file. Copy the properties to the output directory instead of always, and then the configuration file will be generated into the Debug directory.
The procedure is as follows:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap (); fileMap.ExeConfigFilename = Path.Combine (AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\ Unity.Config"); / / find the path to the configuration file Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration (fileMap, ConfigurationUserLevel.None); UnityConfigurationSection section = (UnityConfigurationSection) configuration.GetSection (UnityConfigurationSection.SectionName); IUnityContainer container = new UnityContainer (); section.Configure (container, "testContainer"); IDbInterface db = container.Resolve ("sql"); Console.WriteLine (db.Insert ())
Results:
If you look at the above code, you will find that if it is implemented using a configuration file, the code will not depend on the details, just an interface type. Since there are no details, then the project is modified as follows: remove all the references to the details in the reference (that is, remove DataBase.MSSQL and DataBase.Oracle), and then there are no two DLL in the Debug folder, but at this time you need to copy the two DLL to the Debug directory, otherwise the specific implementation type will not be found when the program is running. This means that the program architecture depends only on interfaces.
As long as there is a reference to the interface in the reference, there is no reference to the specific implementation. Get rid of the dependence on details.
Note: when implementing using a configuration file, you must copy the specific implementation class of the interface to the program directory.
If an additional database is added, you only need to modify the configuration file and copy the new implementation class to the program directory to upgrade the program.
When using the configuration file, you need to define the UnityContainer container as static, so you only need to read the configuration file once.
At this point, the study on "how to use Unity to achieve IOC in C#" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.