依赖注入(Dependeny Injection)简称DI,DI的作用是减少类与类,组件和组件之间的耦合度。依赖注入包括属性注入、构造函数注入。下面我们以公司员工考勤来谈谈依赖注入的应用场景。
公司员工接口和考勤接口
/// <summary> /// 员工接口 /// </summary> public interface IPersonnel { DateTime StartWork { get; set; } DateTime EndWork { get; set; } /// <summary> /// 出勤 /// </summary> void Attendance(); } /// <summary> /// 考勤接口 /// </summary> public interface ICheckIn { /// <summary> /// 考勤 /// </summary> /// <param name="stratwork"></param> /// <param name="endwork"></param> void CheckIn(DateTime stratwork,DateTime endwork); }
场景一:所有的员工考勤方案一样。
/// <summary>
/// 普通员工
/// </summary>
public class GeneralStaf : IPersonnel
{
private DateTime _startWork;
private DateTime _endWork;
private ICheckIn checkin;
public GeneralStaf(DateTime stratwork,DateTime endwork)
{
_startWork = stratwork;
_endWork = endwork;
}
/// <summary>
/// 考勤
/// </summary>
public void Attendance()
{
checkin = new GeneralCheckIn();
checkin.CheckIn(_startWork, _endWork);
}
public DateTime StartWork
{
get
{
return _startWork;
}
set
{
_startWork = value;
}
}
public DateTime EndWork
{
get
{
return _endWork;
}
set
{
_endWork = value;
}
}
}
/// <summary>
/// 通用考勤方案
/// </summary>
public class GeneralCheckIn:ICheckIn
{
public void CheckIn(DateTime stratwork, DateTime endwork)
{
Console.WriteLine("stratwork:" + stratwork);
Console.WriteLine("endwork:" + endwork);
if (stratwork.Hour > 9)
{
Console.WriteLine("you are be late!");
}
if (stratwork.Hour < 18)
{
Console.WriteLine("you are leave early");
}
}
}
客服端代码和执行结果。
static void Main(string[] args) { IPersonnel personnel = new GeneralStaf(DateTime.Now,DateTime.Now.AddHours(8)); personnel.Attendance(); Console.ReadLine(); }
从上面代码红色标记可以看出。GeneralStaf类和GeneralCheckIn存在着耦合。当考勤类变化时,我们不得不修改GeneralStaf类,这也违反了类的封闭原则。
使用依赖注入解耦
将GeneralStaf修改为
public class GeneralStaff : IPersonnel { private DateTime _startWork; private DateTime _endWork; private ICheckIn _checkin; [Required] public ICheckIn checkIn { get { return _checkin; } set { _checkin = value; } } public GeneralStaff() { } public GeneralStaff(DateTime stratwork, DateTime endwork) { _startWork = stratwork; _endWork = endwork; } /// <summary> /// 考勤 /// </summary> public void Attendance() { _checkin.CheckIn(_startWork, _endWork); } public DateTime StartWork { get { return _startWork; } set { _startWork = value; } } public DateTime EndWork { get { return _endWork; } set { _endWork = value; } } }
修改配置文件
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" /> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> </sectionGroup> </configSections> <spring> <context> <!-- using embedded assembly configuration file <resource uri="assembly://Spring.IocQuickStart.MovieFinder/Spring.IocQuickStart.MovieFinder/AppContext.xml"/> --> <!-- using section in App.config --> <resource uri="config://spring/objects" /> </context> <objects xmlns="http://www.springframework.net"> <description>An example that demonstrates simple IoC features.</description> <object id="GeneralStaff" type="IocExample.GeneralStaff, IocExample"> <property name="checkIn" ref="generalCheckin"/> </object> <object id="generalCheckin" type="IocExample.GeneralCheckIn, IocExample" > </object> </objects> </spring> </configuration>
客服端的代码:
static void Main(string[] args) { IApplicationContext context = ContextRegistry.GetContext(); IPersonnel personnel = (IPersonnel)context.GetObject("GeneralStaff"); personnel.StartWork = DateTime.Now; personnel.EndWork = DateTime.Now.AddHours(8); personnel.Attendance(); Console.ReadLine(); }
运行结果: