Unity
The Unity framework is a commonly used IOC framework in C#. Learning Unity suggests that you should have a certain understanding of IOC. Like other IOC frameworks, Unity's role is to use dependency injection and inversion of control to achieve a high degree of decoupling.
Use of Unity
Getting started with Unity is relatively simple. Unlike Java's Spring, which requires a lot of configuration. So let’s learn how to use it right away.
1. Project construction
1. Interface
public interface IFood
{
string Name {
set; get; }
}
2. Implementation class
public class Banana:IFood
{
public string Name {
get; set; } = string.Empty;
}
public class Apple:IFood
{
public string Name {
get; set; } = string.Empty;
}
public class Beef:IFood
{
public string Name {
get; set; } = string.Empty;
}
1. Construction of IOC container
Since it is a program that manages the use of objects, of course, there must be a container to manage the creation and preservation of objects. In this way, you can select the objects you need at the moment of need.
public static IUnityContainer Container = new UnityContainer();
2. Registration and acquisition of instances
1. How to register and obtain the full version
IUnityContainer RegisterInstance(Type type,string name, object instance,LifetimeManager lifetime);
By Container
calling this method, an instance can be registered in the container.
Parameter 1: type
Specify the type of the instance.
Parameter 2: name
Specify the name of the instance.
Parameter 3: instance
Specify the instance to be registered.
Parameter 4: lifetime
Specify the life cycle of the instance (Unity has 6 built-in lifetime management models. The default is to TransientLifetimeManager
obtain a new instance every time )
public static T Resolve<T>(string name);
By Container
calling this method, an instance of the specified name can be obtained.
Generic: T
specify the type of the instance to be obtained
Parameter 1: name
specify the name of the instance to be obtained
Container
An instance with this name will be returned in the container that matches the type.
class Program
{
//新建IOC容器
public static IUnityContainer Container = new UnityContainer();
public static void Main(string[] args)
{
Banana banana = new Banana
{
Name = "香蕉"
};
Apple apple = new Apple
{
Name = "苹果"
};
//注册IFood类型的实例banana到容器中,key为banana。
//TransientLifetimeManager表示每次获取该类型都是一个新实例。
Container.RegisterInstance(typeof(IFood), "banana", banana,
new TransientLifetimeManager());
//获取IFood类型,key为banana的实例
food = Container.Resolve<IFood>("banana");
//因为每次获取该类型都新创建一个实例,因此名字不是香蕉而是空字符串。
Console.WriteLine("取得的食物是:" + food.Name);
Console.ReadLine();
}
}
2. The life cycle of the instance
Abstract class of life cycle: LifetimeManager
This abstract class describes the life cycle of an instance.
There are 6 sub-classes that represent 6 different life cycles of an instance.
TransientLifetimeManager
Generate a new type object instance for each request. (Default)
When this parameter is used, every instance obtained is brand new.
ContainerControlledLifetimeManager
Each request is a registered instance (singleton mode)
. Singleton mode can be realized when this parameter is used. The instance obtained each time is the same.
For others, please read Object lifetime management in Unity container . No expansion here.
3. Simplified method
1) Omit the life cycle
IUnityContainer RegisterInstance( Type type, string name, object instance);
After the life cycle is omitted, other parameter functions remain unchanged, and the life cycle will use the default life cycle.
That is, each acquisition is a brand new instance.
2) Omit the name
IUnityContainer RegisterInstance(Type type,object instance);
After the instance name is omitted, the named instance acquisition method cannot be used.
Only use to public static T Resolve<T>();
obtain an instance of this type.
When using keys to obtain instances, you can accurately obtain different instances of the same type.
When the key is not used, only one instance of that type can be stored in a type. The second registration will overwrite the previously registered instance.
If you use the same key to register the instance. Then it will overwrite the previously registered instance of this key.
public static void Main(string[] args)
{
//注册
Banana banana = new Banana
{
Name = "香蕉"
};
Apple apple = new Apple
{
Name = "苹果"
};
Beef beef = new Beef
{
Name = "牛肉"
};
//注册IFood类型的实例banana。
Container.RegisterInstance(typeof(IFood),banana);
//使用
//获取IFood类型的实例
var food =Container.Resolve<IFood>();
Console.WriteLine("取得的食物1是:"+food.Name);
//为容器注入新的IFood类型实例会覆盖之前注册的IFood实例
Container.RegisterInstance(typeof(IFood),apple);
//获取IFood类型的实例
food = Container.Resolve<IFood>();
Console.WriteLine("取得的食物2是:" + food.Name);
//注册一个key为'banana'的实例
Container.RegisterInstance(typeof(IFood), "banana", banana,
new ContainerControlledLifetimeManager());
food = Container.Resolve<IFood>("banana");
Console.WriteLine("取得的食物1是:" + food.Name);
//再注册一个key为'banana'的实例
Container.RegisterInstance(typeof(IFood), "banana", beef,
new ContainerControlledLifetimeManager());
food = Container.Resolve<IFood>("banana");
Console.WriteLine("取得的食物2是:" + food.Name);
Console.ReadLine();
}
Result:
3) Omit type
IUnityContainer RegisterInstance(object instance);
When the type is not specified, the default declaration is the type of the registered instance.
public static void Main(string[] args)
{
//注册
Banana banana = new Banana
{
Name = "香蕉"
};
//注册IFood类型的实例banana。
Container.RegisterInstance(banana);
//使用
//获取IFood类型的实例
var food =Container.Resolve<Banana>();
Console.WriteLine("取得的食物1是:"+food.Name);
}
IFood
An instance of the type cannot be obtained at this time . Because bananas are of Banana
type. But if you declare bananas as a IFood
type, you can also use IFood
type acquisition.
This shows that the type used when registering in the container is the type when the instance was declared, not the type of the instance itself.
4) Use generics to specify the registration type and
IUnityContainer RegisterInstance<T>(object instance);
only specify the type and instance.
IUnityContainer RegisterInstance<T>(string name, object instance);
Specify the type, key value and instance.
IUnityContainer RegisterInstance<T>(string name, object instance,LifetimeManager lifetime);
Specify the type, key value, instance, and life cycle.
Move the type of the instance from the parameter to the method generic. The parameters are reduced, and the actual use method remains unchanged.
Later, we will introduce other registration methods and configuration methods. To be continued~