1. Preface
Before talking about the design pattern , there is one more implementation technique. It is dependency injection.
why would you introduce it?
Abstract (interface) programming is the core of grasping the "dependency inversion principle" (which is described later in this article).
Dependency inversion is a client program that relies on a "relatively stable" interface rather than a "relatively many" subclass. That is, the client program does not rely on subclasses.
The principle of design also has a "Richter substitution principle", which is viewed from the point of view of the pattern object, which refers to the "relatively changeable" subclass as its interface (or parent class). Where the parent class appears, the subclass can be substituted .
When it comes to "upside down", it may be dizzy. Then say "Zheng" first. Relying on the positive is the dependence between classes is a real implementation of the dependency between classes, that is, to implement programming, but also the usual way of thinking. I have to use a computer to have a computer and rely on it. Writing a program requires an abstraction of something in the real world, which forms an abstract class or interface. System design generally relies on abstraction, in this way instead of the human mind in the dependencies between things, inversion is also produced.
But abstract things, is the template of specific things, and ultimately rely on concrete implementation. How to make the client program not dependent on the specific type, you can use the dependency injection method.
Hey! The explanation was very much around. I'm sorry! Confused. The demonstration of the example process to understand again.
2. Overview of Dependency Injection
A client program relies on an object (or class) that is generally abstracted to form an abstract class or interface so that the client can get rid of the specific type it relies on.
Dependency Injection (Dependency injection, referred to as DI) can also be called control inversion (inverse of controls, referred to as IOC). The two terms are essentially the same.
3. Case scenario
The client program needs to get the current time. First, create a time provider class whose code:
// time provider Class Public class Timeprovider { public DateTime currentdate { get return DateTime.Now; } } }
Used in client programs (Web programs):
[Route ("Api/[controller]")] Public class Timeprovidercontroller:controller { // instantiation New Timeprovider (); [HttpGet] Public string Get () { return TP. Currentdate.tostring (); } }
So the client program relies on the specific timeprovider type. We do the abstraction and implement it.
To create an interface:
// Time Provider Interface class Public Interface Itimeprovider { get;} }
Realize:
// time Provider Implementation class Public class Systemtimeprovider:itimeprovider { public DateTime currentdate { get return DateTime.Now; } } }
Client program:
Public classTimeprovidercontroller:controller {//instantiation of//timeprovider TP = new Timeprovider (); //TP variable Surface type is Itimeprovider, actual type or Systemtimeprovider//TODO: Client program does not get rid of specific systemtimeprovider typeItimeprovider TP =NewSystemtimeprovider (); [HttpGet] Public stringGet () {returnTP. Currentdate.tostring (); } }
The question comes, how does the client program get rid of specific systemtimeprovider type dependencies?
4. Reflection mode
Introduce an intermediate class to assemble the type:
//Assembly Class Public classAssembler {//A dictionary that holds the corresponding relationship between abstract types and specific types StaticDictionary<type, type> d =NewDictionary<type, type>(); StaticAssembler () {//specific types required for registering abstract types//TODO: Can be defined by configuration fileD.add (typeof(Itimeprovider),typeof(Systemtimeprovider)); } Private Static ObjectCreate (Type type) {if(Type = =NULL) || !D.containskey (type)) { Throw NewNullReferenceException (); } returnactivator.createinstance (D[type]); } Public StaticT create<t>() { returnT Create (typeof(T)); } }
Client program:
Public classTimeprovidercontroller:controller {//instantiation of//timeprovider TP = new Timeprovider (); //TP variable Surface type is Itimeprovider, actual type or Systemtimeprovider//TODO: Client program does not get rid of specific systemtimeprovider type//itimeprovider TP = new Systemtimeprovider (); //by assembling the method of the class to instantiate, so as to get rid of the concrete type dependenceItimeprovider TP = assembler.create<itimeprovider>(); [HttpGet] Public stringGet () {returnTP. Currentdate.tostring (); } }
The client program relies only on interface Itimeprovider and group assembler, without knowing the existence of a specific type Systemtimeprovider. The static structure of its class diagram:
Note: The assembler is less powerful than using the Di frame. Of course, you can also use the Factory mode (follow-up article introduction) to replace.
5. Dependency Injection Framework
The DI framework is built around a container object that resolves dependencies when the container object is bound to certain configuration information (or method calls).
The more popular di frame: Autofac,catlewindsor,ninject,sprint.net,structuremap,untity,mef and so on.
The following are the included Di frames using the MVC6 (EntityFramework7 also, or individually introduced):
Configureservices method Configuration in Startup.cs:
Public void configureservices (iservicecollection services) { //TODO: You can define //services through a configuration file. Addscoped<itimeprovider, systemtimeprovider> (); // single-case mode Services. Addsingleton<itimeprovider, systemtimeprovider>(); // Services. Addinstance<itimeprovider> (New Systemtimeprovider ()); Services. Addmvc (); }
6. How to Construct
Client program:
Public class Timeprovidercontroller:controller { privatereadonly itimeprovider tp; Public Timeprovidercontroller (Itimeprovider _tp) { this. TP= _tp; } [HttpGet] Public string Get () { return TP. Currentdate.tostring (); } }
7. Set the value mode
Client program:
Public classTimeprovidercontroller:controller {//private readonly itimeprovider TP; //Public Timeprovidercontroller (Itimeprovider _tp)//{ //this.tp = _TP; //} PublicItimeprovider TP {Get;Set; } [HttpGet] Public stringGet () {returnTP. Currentdate.tostring (); } }
The code is formatted like this, without constructors. However, the current Asp.net5 di can not be injected using the Set Value attribute method.
It is also matched with a group of classes, without the DI framework:
public class Timeprovidercontroller:controller { public itimeprovider TP {get ; set // assembly class to get type instantiation, no use of Di framework public Timeprovidercontroller () {TP = assembler.create< Itimeprovider> (); } [HttpGet] public string Get () { return TP. Currentdate.tostring (); } }
8. Summary of this chapter
On the dependency injection method, there are interface injection mode, feature annotation injection mode, and so on, these are not commonly used, do not RIP.
Dependency injection can also be called a design pattern, but as the preface says, it is a technique of implementation or design.
The common construction injection and the setting value injection method, must grasp. Difference between the two?
Construction injection is a one-time, and is determined when the client type is constructed. It is suitable for an object whose life cycle is not long and does not need to be re-adapted during its existence.
The value method is for the long life cycle of customer objects, can be injected at any time during the operation, more flexible.
9. Appendix
The above example source code solution directory:
Description:
Givecase.modeling is a modeling design
Givecase.web is the presentation layer
Givecase.service is the business layer
It, to 290576772 QQ Group space download.
"Design Pattern" Summary Series 02: Dependency Injection