I spent a day yesterday searching IOC/DI articles and Unity articles in the garden.
First, I would like to provide a few links to a good article:
Unity Application Block official website http://www.codeplex.com/unity
[Object Builder Application Block] http://www.cnblogs.com/zhenyulu/articles/641728.html organized by Lu Zhenyu
Lu Zhenyu [Do you really understand Ioc and AOP?] Http://www.cnblogs.com/zhenyulu/articles/233966.html
[Inversion of Control Containers and the Dependency Injection pattern] http://www.cnblogs.com/me-sa/archive/2008/07/30/IocDI.html
Kids kids [unity series] http://www.cnblogs.com/kebixisimba/archive/2008/05/19/1202467.html
NEE's [Unity configuration: Use of typeConverter] http://www.cnblogs.com/nickyao/archive/2008/05/04/1181804.html
Warmth & Chilliness's [Unity -- native Ioc framework under. NET, let some people use it first] http://www.cnblogs.com/think8848/archive/2008/10/25/1319616.html
Basically, I have read the above articles with patience, and the "literacy" work on related knowledge points has almost been completed.
Here is just an example of my practice, and I will give some personal opinions.
Application Scenario: A Basic data operation is required for numbers (only addition/multiplication is implemented in this example)
Add a reference to Microsoft. Practices. Unity. dll.
Interfaces and classes for testing:
/// <Summary>
/// Interface
/// </Summary>
Public interface Icalculate
{
Int Calculate (params int [] );
Double Calculate (params double [] );
String GetOperationName ();
}
/// <Summary>
/// Addition operation
/// </Summary>
Public class Addtive: Icalculate
{
/// <Summary>
/// Note: there must be at least one constructor. Otherwise, when you use the configuration file Resolve <Icalculate>, the system will prompt that Icalculate is an interface and there is no constructor. Therefore, you cannot create an instance on the cloud, however, it is interesting that hard encoding is successful.
/// </Summary>
Public Addtive (){}
Public int Calculate (params int [])
{
Int Result = 0;
Foreach (int x in)
{
Result + = x;
}
Return Result;
}
Public double Calculate (params double [])
{
Double Result = 0.0;
Foreach (double x in)
{
Result + = x;
}
Return Result;
}
Public string GetOperationName ()
{
Return "addition ";
}
}
/// <Summary>
/// Multiplication
/// </Summary>
Public class Multiplication: Icalculate
{
Public Multiplication (){}
Public int Calculate (params int [])
{
Int Result = 1;
Foreach (int x in)
{
Result * = x;
}
Return Result;
}
Public double Calculate (params double [])
{
Double Result = 1.0;
Foreach (double x in)
{
Result * = x;
}
Return Result;
}
Public string GetOperationName ()
{
Return "multiplication ";
}
}
/// <Summary>
/// (Four rules) Operation Manager
/// </Summary>
Public class CalcManager
{
Private Icalculate _ calc;
Public CalcManager (Icalculate IC)
{
_ Calc = IC;
}
// [InjectionMethod]
// Public void SetCalculate (Icalculate IC ){
// _ Calc = IC;
//}
Public void Compute (params int [])
{
String _ paramName = "";
Foreach (int x in)
{
_ ParamName + = x. ToString () + ",";
}
_ ParamName = _ paramName. Trim (',');
Console. WriteLine ("{0} {1} Calculation Result: {2}", _ paramName, _ calc. GetOperationName (), _ calc. Calculate ());
}
Public void Compute (params double [])
{
String _ paramName = "";
Foreach (double x in)
{
_ ParamName + = x. ToString () + ",";
}
_ ParamName = _ paramName. Trim (',');
Console. WriteLine ("{0} {1} Calculation Result: {2}", _ paramName, _ calc. GetOperationName (), _ calc. Calculate ());
}
}
For comparison, we first use the traditional method to call and try:
Static void Main (string [] args)
{
# Region uses the traditional method of dependency injection.
CalcManager CM = new CalcManager (new Addtive ());
CM. Compute (1, 2, 3, 4, 5); // calculate the sum of 1, 2, 4, 5
// CM = new CalcManager (new Multiplication ());
// CM. Compute (1, 2, 3, 4, 5); // calculate the product of 1, 2, 3, 4, 5
# Endregion
Console. ReadLine ();
}
Although it is easy to understand, it is not highly scalable. If division, square, subtraction... and other algorithms are added later, isn't this code required every time? The reason is that interfaces, algorithm entities, and calling programs are too coupled.
Next, we use Unity for another method:
Using System;
Using Microsoft. Practices. Unity;
Using Microsoft. Practices. Unity. Configuration;
Using System. Configuration;
Static void Main (string [] args)
{
# Region uses dependency injection (hard encoding)
IUnityContainer container = new UnityContainer ();
Container. RegisterType <Icalculate, Addtive> () // inject addition class
. RegisterType <CalcManager> (); // injection Manager
CalcManager CM = container. Resolve <CalcManager> (); // gets the CalcManager instance.
CM. Compute (1.1, 2.9, 3.1, 4, 5 );
// Container. RegisterType <Icalculate, Multiplication> (); // continue to inject the Multiplication class
// CM = container. Resolve <CalcManager> ();
// CM. Compute (1, 2, 3, 4, 5 );
# Endregion
Console. ReadLine ();
}
From the code alone, I only changed the writing method and idea, but it still belongs to the "hard encoding" method. If you want to add other algorithms or replace them with other algorithms, you still need to modify this code. (It seems like it's just a waste of fun? Haha)
In addition to this hard encoding method, Unity also allows you to write injection rules/mappings to the configuration file.
First, modify App. Config. The content is roughly as follows:
<? Xml version = "1.0" encoding = "UTF-8"?>
<Configuration>
<ConfigSections>
<Section name = "unity" type = "Microsoft. Practices. Unity. Configuration. UnityConfigurationSection, Microsoft. Practices. Unity. Configuration, Version = 1.2.0.0, Culture = neutral"/>
</ConfigSections>
<Unity configSource = "config \ DI. config"/>
</Configuration>
At the same time, create a new config directory and put the DI. config file under this directory. content:
<? Xml version = "1.0"?>
<Unity>
<TypeAliases>
<TypeAlias alias = "ic1c" type = "UnityStudy. Icalculate, UnityStudy"/>
<TypeAlias alias = "Add" type = "UnityStudy. Addtive, UnityStudy"/>
<TypeAlias alias = "Mul" type = "UnityStudy. Multiplication, UnityStudy"/>
<TypeAlias alias = "CM" type = "UnityStudy. CalcManager, UnityStudy"/>
</TypeAliases>
<Containers>
<Container>
<Types>
<Type = "ic1c" mapTo = "Mul"/>
<! -- When the experiment is completed, the following line can run without adding a program, as long as the CalcManager has a constructor with the parameter Icalculate or (injection) just set the method. [See the comments in CalcManager]. Unity is indeed "intelligent" at this point. -->
<Type = "CM"/>
</Types>
</Container>
</Containers>
</Unity>
Call the code in another way:
Static void Main (string [] args)
{
# Region uses dependency injection (configuration file Mode)
IUnityContainer container = new UnityContainer ();
UnityConfigurationSection section = (UnityConfigurationSection) ConfigurationManager. GetSection ("unity ");
Section. Containers. Default. Configure (container );
CalcManager CM = container. Resolve <CalcManager> ();
CM. Compute (1, 2, 3, 4, 5 );
# Endregion
Console. ReadLine ();
}
Taking a closer look at this time, the Code has completely failed to find Addtive, Multiplication and other specific class names, and the entire program is completely dependent on the relevant nodes in the configuration file (in fact, from the perspective of OO, is based on the programming interface Icalculate and the combination of different objects to make this all possible ).
If we want to replace the multiplication operation with the addition operation, it is too easy.
<Type = "ic1c" mapTo = "Mul"/>
Change
<Type = "ic1c" mapTo = "Add"/>
You do not need to change the line of the original call code!
Finally, in addition to implementing IOC/DI, Unity also has some other purposes, such as implementing the single-piece mode (and this implementation method is more flexible. For example, we can make any common class, only one instance is returned in the life cycle of the container. This is not possible in the traditional single-piece mode, "setting hard-coded classes to single-piece instances)