關於mvc裏面的依賴注入和ninject的使用

依賴注入:爲了在引用接口的方法的時候爲了耍帥,不引用實現這個接口方法的類,導致了一系列解決方案,實際我感覺只是把接口和對應的實現類放在了一起,方便修改,本質貌似沒變(個人見解,不對請在留言區噴我)。

可能第一段話比較難理解,先看一個例子:

沒有依賴注入的情況:

有一個發送郵件的接口(IEmailSender):

public interface IEmailSender
    {
        string SendEmail(string str);
    }

需要一個類(MyEmailSender)來實現這個接口:

public class MyEmailSender : IEmailSender
    {
        public string SendEmail(string str)
        {
            return "發送內容:" + str;
        }
    }

然後我們在需要發郵件的時候,通常就這樣做了:

IEmailSender mySender = new MyEmailSender();//引入了接口類,和實現這個接口的方法的類
mySender.SendEmail("123");//爲了使用SendEmail,我們引用了兩個類

從上面的代碼可以看出,我們爲了調用一個發郵件的方法,使用了兩個類,如果MyEmailSender這個類改了名字或者修改了話,就要這裏也要改,大牛們就說,這個的耦合性太高,不好,應該做到只關聯接口,但是這不可能,我甚至覺得,不要用接口不就好了嗎?確實開發有時候用的接口也不多,就寫個普通類就好,但是,大神的世界我們不懂,接口也有接口的好處,接口就是要依賴於這個實現接口的類的,所以,依賴注入就是解決這樣的情況。

個人理解:當使用接口的方法的時候才考慮使用依賴注入。

具體mvc裏面怎麼用,可以使用一個第三方dll,ninject,github:https://github.com/ninject/Ninject

建議使用nu'get獲取即可。

使用依賴注入之後的樣子:

接口類和實現接口方法的類不需要修改,主要修改的是調用的時候:

//1:創建一個Ninject的內核
IKernel ninject = new StandardKernel();
//2:就是配置Ninject內核,其實就是將實現類和接口類綁定在一起
ninject.Bind<IEmailSender>().To<MyEmailSender>();
//3:最後一步就是使用Ninject創建一個對象了
IEmailSender mySender = ninject.Get<IEmailSender>();
mySender.SendEmail("123");

從原來的兩行代碼變成了四行代碼,呵呵了,怎麼越加解耦越加多代碼,並且還是引用了實現接口的方法的類啊,我只能說,不綁定,怎麼可能知道是對應的類,很明顯第一二行是可以放在一個初始化類裏面,然後真正使用的時候就用下面兩行代碼就可以了,所以開頭就說了:感覺只是把接口和對應的實現類放在了一起,方便修改,本質貌似沒變(個人見解,不對請在留言區噴我)。

所以在mvc裏面:

初始化的注入類:NinjectControllerFactory

以後所有的接口和實現接口方法的類都綁定在這裏了

public class NinjectControllerFactory : DefaultControllerFactory
    {
        private IKernel ninjectKernel;

        public NinjectControllerFactory()
        {
            ninjectKernel = new StandardKernel();
            AddBindings();
        }

        private void AddBindings()
        {
            ninjectKernel.Bind<IEmailSender>().To<MyEmailSender>();//綁定關係都在這裏了
        }

        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);//這裏的作用就是把這些綁定關係傳遞到控制器上面
        }
    }

然後在Global.asax裏面的Application_Start方法裏面加入這一句:

ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());

這是第一種方法,第二種是這樣:

public class NinjectResolver : IDependencyResolver
    {
        private IKernel kernel;
        public NinjectResolver()
        {
            this.kernel =new StandardKernel();
            AddBinding();
        }
        public IEnumerable<Object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }
        public Object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }
        void AddBinding()
        {
            kernel.Bind<IEmailSender>().To<MyEmailSender>();
        }
    }

然後在Global.asax裏面的Application_Start方法裏面加入這一句:

DependencyResolver.SetResolver(new NinjectResolver());//註冊Ioc容器

兩種都可以,記得global裏面的代碼更換就行

然後在控制器裏面就可以通過構造函數獲得了,具體爲什麼也說不清,網上查的就是這樣:

private IEmailSender _sender;
public HomeController(IEmailSender sender) {
       _sender = sender;//通過控制器的構造函數獲取了這個接口
}
public ActionResult Index()
{
      _sender.SendEmail("123");//使用這個接口的方法
      return View();
}

其實可以看出,是真的沒有引用到MyEmailSender這個類,把他們放在一起了,其實說到最後,這樣是不是好的做法,不敢說,說不定以後有更好的方法,現在大家都這樣用,就這樣了,並且.net core的依賴注入更加強烈了,不需要使用ninject了,微軟直接集成了,回頭再重複看看,以前core時候的注入看的一臉懵逼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章