Unity Application Block(Unity)是Microsoft模式和实践团队(Patterns & Practices team)推出的一个开源依赖注入容器。它是.NET Framework的一个组件,旨在简化应用程序的构建过程,提高代码的可测试性和可维护性。
Unity Application Block提供了以下功能:
总的来说,Unity Application Block是一个强大的依赖注入容器,可以帮助.NET开发人员构建可测试、可维护和灵活的应用程序。
定义接口
internal interface IComputer
{
}
internal interface IKeyboard
{
}
internal interface IMouse
{
}
internal interface IPerson
{
IComputer Computer { get; set; }
IKeyboard Keyboard { get; set; }
IMouse Mouse { get; set; }
void Work();
}
定义实现类
internal class ConstructBase
{
public ConstructBase()
{
Console.WriteLine($"{this.GetType().Name} - 被构造了");
}
}
internal class LenovoComputer : ConstructBase, IComputer
{
public LenovoComputer() : base() { }
}
internal class TogarKeyboard : ConstructBase, IKeyboard
{
public TogarKeyboard() : base() { }
}
internal class LogitechMouse : ConstructBase, IMouse
{
public LogitechMouse() : base() { }
}
internal class Programmer : ConstructBase, IPerson
{
public IComputer Computer { get; set; }
public IKeyboard Keyboard { get; set; }
public IMouse Mouse { get; set; }
public Programmer(IComputer computer, IKeyboard keyboard, IMouse mouse) : base()
{
Computer = computer;
Keyboard = keyboard;
Mouse = mouse;
}
public void Work()
{
Console.WriteLine("The programmer is distributing software...");
}
}
依赖注入
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>();
container.RegisterType<IKeyboard, TogarKeyboard>();
container.RegisterType<IMouse, LogitechMouse>();
container.RegisterType<IPerson, Programmer>();
IPerson programmer = container.Resolve<IPerson>(;
programmer.Work();
输出
LenovoComputer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
Programmer - 被构造了
The programmer is distributing software...
使用[InjectionConstructor]
特性标注依赖注入时使用构造函数,默认使用参数最多的构造函数
[InjectionConstructor]
public Gamer(IComputer computer)
{
Computer = computer;
}
使用[Dependency]
标注需要注入的属性
[Dependency]
public IKeyboard Keyboard { get; set; }
方法注入是为了给方法传递参数,与构造函数注入的代码相似
[InjectionMethod]
public void Inject(IMouse mouse)
{
this.Mouse = mouse;
}
定义类
internal class Gamer : IPerson
{
public IComputer Computer { get; set; }
[Dependency]
public IKeyboard Keyboard { get; set; }
public IMouse Mouse { get; set; }
[InjectionConstructor]
public Gamer(IComputer computer)
{
Computer = computer;
}
[InjectionMethod]
public void Inject(IMouse mouse)
{
this.Mouse = mouse;
}
public void Work()
{
Console.WriteLine("The player is playing...");
}
}
调用
IUnityContainer container = new UnityContainer();
container.RegisterType<IPerson, Gamer>();
container.RegisterType<IComputer, LenovoComputer>();
container.RegisterType<IKeyboard, TogarKeyboard>();
container.RegisterType<IMouse, LogitechMouse>();
IPerson person = container.Resolve<IPerson>();
person.Work();
输出
LenovoComputer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
The player is playing...
结果
注入顺序:构造函数注入 > 属性注入 > 方法注入
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>();
container.RegisterType<IKeyboard, TogarKeyboard>();
container.RegisterType<IMouse, LogitechMouse>();
container.RegisterType<IPerson, Gamer>();
container.RegisterType<IPerson, Programmer>();
IPerson person = container.Resolve<IPerson>();
person.Work();
输出
LenovoComputer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
Programmer - 被构造了
The programmer is distributing software...
调换Gamer和Programmer的注册顺序:
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>();
container.RegisterType<IKeyboard, TogarKeyboard>();
container.RegisterType<IMouse, LogitechMouse>();
container.RegisterType<IPerson, Programmer>();
container.RegisterType<IPerson, Gamer>();
IPerson person = container.Resolve<IPerson>();
person.Work();
输出
LenovoComputer - 被构造了
Gamer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
The player is playing...
结论
同一接口多次注册时,后注册的会覆盖前面注册的,若需要实现多重注册,需要指定名称
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>();
container.RegisterType<IKeyboard, TogarKeyboard>();
container.RegisterType<IMouse, LogitechMouse>();
container.RegisterType<IPerson, Programmer>("Programmer");
container.RegisterType<IPerson, Gamer>("Gamer");
IPerson programmer = container.Resolve<IPerson>("Programmer");
programmer.Work();
IPerson gamer = container.Resolve<IPerson>("Gamer");
gamer.Work();
输出
LenovoComputer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
Programmer - 被构造了
The programmer is distributing software...
LenovoComputer - 被构造了
Gamer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
The player is playing...
修改接口
internal interface IMouse
{
string Type { get; set; }
}
修改实现类
internal class LogitechMouse : ConstructBase, IMouse
{
public LogitechMouse() : base() { }
public LogitechMouse(string type) : base()
{
Type = type;
}
public string Type { get; set; }
}
调用
IUnityContainer container = new UnityContainer();
container.RegisterType<IMouse, LogitechMouse>(new InjectionConstructor("502"));
IMouse mouse = container.Resolve<IMouse>();
Console.WriteLine("Type: " + mouse.Type);
输出
LogitechMouse - 被构造了
Type: 502
多次注册同样覆盖
IUnityContainer container = new UnityContainer();
container.RegisterType<IMouse, LogitechMouse>(new InjectionConstructor("502"));
IMouse mouse_502 = container.Resolve<IMouse>();
Console.WriteLine("Type: " + mouse_502.Type);
container.RegisterType<IMouse, LogitechMouse>(new InjectionConstructor("304"));
IMouse mouse_304 = container.Resolve<IMouse>();
Console.WriteLine("Type: " + mouse_304.Type);
输出
LogitechMouse - 被构造了
Type: 502
LogitechMouse - 被构造了
Type: 304
生命周期类型:
默认生命周期
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>();
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");
输出
LenovoComputer - 被构造了
LenovoComputer - 被构造了
computer0: 15368010
computer1: 4094363
computer0 == computer1: False
单例生命周期
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>(new SingletonLifetimeManager());
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");
输出
LenovoComputer - 被构造了
computer0: 15368010
computer1: 15368010
computer0 == computer1: True
每个线程一个生命周期
IUnityContainer container = new UnityContainer();
container.RegisterType<IComputer, LenovoComputer>(new PerThreadLifetimeManager());
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
IComputer computer2 = null;
Task.Run(() =>
{
computer2 = container.Resolve<IComputer>();
}).Wait();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine("computer2: " + computer2.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");
Console.WriteLine($"computer0 == computer2: {computer0 == computer2}");
输出
LenovoComputer - 被构造了
LenovoComputer - 被构造了
computer0: 15368010
computer1: 15368010
computer2: 4094363
computer0 == computer1: True
computer0 == computer2: False
Nuget
配置文件
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
configSections>
<unity>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
<containers>
<container name="Unity_Container">
<register type="IoCStudy.Interfaces.IKeyboard, IoCStudy" mapTo="IoCStudy.Entities.TogarKeyboard, IoCStudy"/>
<register type="IoCStudy.Interfaces.IMouse, IoCStudy" mapTo="IoCStudy.Entities.LogitechMouse, IoCStudy"/>
<register type="IoCStudy.Interfaces.IComputer, IoCStudy" mapTo="IoCStudy.Entities.LenovoComputer, IoCStudy"/>
<register type="IoCStudy.Interfaces.IPerson, IoCStudy" mapTo="IoCStudy.Entities.Programmer, IoCStudy" name="Programmer"/>
<register type="IoCStudy.Interfaces.IPerson, IoCStudy" mapTo="IoCStudy.Entities.Gamer, IoCStudy" name="Gamer"/>
container>
containers>
unity>
configuration>
调用
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "DI-Unity.config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "Unity_Container");
IPerson programmer = container.Resolve<IPerson>("Programmer");
programmer.Work();
IPerson gamer = container.Resolve<IPerson>("Gamer");
gamer.Work();
输出
LenovoComputer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
Programmer - 被构造了
The programmer is distributing software...
LenovoComputer - 被构造了
Gamer - 被构造了
TogarKeyboard - 被构造了
LogitechMouse - 被构造了
The player is playing...
IOC容器:Unity_51CTO博客_unity navmesh
IOC容器Unity三种注入总结_unity容器-CSDN博客
IOC容器之Unity与AutoFac_unity autofac-CSDN博客
控制容器的反转和依赖关系注入 模式 (martinfowler.com)
unitycontainer/unity at release/6.0.0 (github.com)
Unity 容器介绍 |Unity 容器 (unitycontainer.org)