写在前面:
依赖注入这个玩意很多人其实都接触过,但可能没有细究其中的原理。
比如Controller的构造函数中,只要你传入一些接口,应用自动就给你处理了创建的过程,无需你手动去new 一个实例并穿进去来创建Controller.
比如:
public class LoginController : BaseController { public LoginController(IOptions<AppSet> option) : base(option) { } }
或者
public class APIController : ControllerBase { private readonly IHttpContextAccessor httpContextAccessor; // GET api/values public APIController(IHttpContextAccessor httpContextAccessor) { this.httpContextAccessor = httpContextAccessor; } }
技术分析:
试想,如果没有一个注入机制,我们肯定得来 new 创建对象了。new不但类,而且后期还不好改,因为有100个地方则new 了100个地方,想换一个接口的实现类,就需要到处去修改了。于是有人就推出了专门解决类似问题的框架,本文介绍:StructureMap.
使用场景:(假设有验证码登录,短信验证登录...):
public interface ILog { void Work(); } public interface ILogin { void Work(); } public interface IReposibility { void Work(); } public interface ISmsCode { void Work(); } public interface IVerifyCode { void Work(); }
相关的实现类:
/// <summary> /// 账号密码+短信的登录 /// </summary> public class LoginWithSmsCode : ILogin { /// <summary> /// /// </summary> /// <param name="reposibility"></param> /// <param name="verifyCode"></param> public LoginWithSmsCode(IReposibility reposibility, ISmsCode smsCode) { ConfigLab.Utils.SaveLog($"LoginWithSmsCode:被创建"); } public void Work() { } } /// <summary> /// 账号密码+验证码的登录 /// </summary> public class LoginWithVerifyCode:ILogin { /// <summary> /// /// </summary> /// <param name="reposibility"></param> /// <param name="verifyCode"></param> public LoginWithVerifyCode(IReposibility reposibility,IVerifyCode verifyCode) { ConfigLab.Utils.SaveLog($"LoginWithVerifyCode:被创建"); } public void Work() { } } public class SmsCode:ISmsCode { public SmsCode(IReposibility reposibility,ILog log) { ConfigLab.Utils.SaveLog($"SmsCode:被创建"); } public void Work() { } } public class VerifyCode :IVerifyCode { public VerifyCode(IReposibility reposibility, ILog log) { ConfigLab.Utils.SaveLog($"VerifyCode:被创建"); } public void Work() { } } public class Reposibility:IReposibility { public Reposibility() { ConfigLab.Utils.SaveLog($"Reposibility:被创建"); } public void Work() { } } public class Log:ILog { public Log() { ConfigLab.Utils.SaveLog($"Log:被创建"); } public void Work() { } }
StructureMap使用-容器初始化:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using StructureMap; using ConfigLab.LabCore.IocLab.Interfaces; using ConfigLab.LabCore.IocLab; using System.Runtime.CompilerServices; namespace ConfigLab.LabCore { /// <summary> /// 功能简介:StructureMap容器的初始化 /// 作者:http://cnblogs.com/taohuadaozhu /// 备注:这里只用了一些简单的处理,还有自动扫描程序集scan等,可自行查找StructureMap的资料. /// </summary> public static class AppRunContext { private static Container _gContainner = null; public static Container gContainner { get { if (_gContainner == null) { Init(); } return _gContainner; } } /// <summary> /// 功能简介:初始化(应用程序只需一次初始化),可以放到服务的初始化或者asp.net mvc中Application_Start中。 /// </summary> private static void Init() { _gContainner = new Container(_=> { _.For<ILogin>().Use<LoginWithVerifyCode>(); _.For<ISmsCode>().Use<SmsCode>(); _.For<IVerifyCode>().Use<VerifyCode>(); _.For<ILog>().Use<Log>(); _.For<IReposibility>().Use<Reposibility>(); }); } } }
StructureMap使用-创建接口的实现类对象:
ILogin login= AppRunContext.gContainner.GetInstance<ILogin>();//这里每次创建无需指定是验证码还是短信验证,在初始化的时候规定了,如果修改只需修改初始化容器那块。