本系列主要翻譯自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想看英文原版的可訪問http://www.dotnettricks.com/free-ebooks自行下載。該書主要分為兩部分,ASP.NET MVC 5、ASP.NET WEB API2。本書最大的特點是以面試問答的形式進行展開。通讀此書,會幫助你對ASP.NET MVC有更深層次的理解。
由于個人技術(shù)水平和英文水平也是有限的,因此錯誤在所難免,希望大家多多留言指正。
系列導(dǎo)航
Asp.net mvc 知多少(一)
Asp.net mvc 知多少(二)
Asp.net mvc 知多少(三)
Asp.net mvc 知多少(四)
Asp.net mvc 知多少(五)
Asp.net mvc 知多少(六)
Asp.net mvc 知多少(七)
Asp.net mvc 知多少(八)
Asp.net mvc 知多少(九)
Asp.net mvc 知多少(十)
本節(jié)主要講解了依賴注入
Q91. 什么是松耦合以及如何實現(xiàn)松耦合?
Ans. MVC設(shè)計模式最重要的功能之一就是關(guān)注點分離。
因此,我們的應(yīng)用程序的模塊應(yīng)該盡可能的保持獨立,也就是保持松耦合。它促使更容易的對應(yīng)用程序進行測試和維護。
通過使用Dependency Injection (DI,依賴注入)可以幫忙我們實現(xiàn)應(yīng)用程序各個模塊之間的松耦合。
Q92. 什么是Dependency Inversion Principle (DIP,依賴倒置原則)和IoC(控制反轉(zhuǎn))?
Ans. 依賴倒置原則講的是:
- 高層模塊不應(yīng)該依賴低層模塊,它們都應(yīng)該依賴于抽象。
- 抽象不應(yīng)該依賴于細(xì)節(jié)(具體的實現(xiàn))。但細(xì)節(jié)應(yīng)該依賴于抽象。
依賴倒置原則幫助我們開發(fā)松耦合的代碼,并確保了高層模塊依賴于抽象而不是低層模塊具體的實現(xiàn)。
控制反轉(zhuǎn)模式是對DIP的一種實現(xiàn)。
IOC指的是一種框架或運行時的編程風(fēng)格,用來控制程序流程。
IOC意味著我們可以改變常規(guī)的控制方式。它在DIP下得以實現(xiàn)。許多基于.net框架的軟件開發(fā)都使用IOC。
IOC更多的是一個通用術(shù)語,不僅僅局限于DI。DI和Service Locator(服務(wù)定位器)模式是對IOC模式的一種實現(xiàn)方式。
舉例來說,假設(shè)你客戶端的類需要使用一個Service類組件,那么最佳實踐是讓你的客戶端類知道有個IService接口而不是Service類,這種方式下,你可以隨時改變IService的具體實現(xiàn)而不會中斷已經(jīng)部署的代碼。
IoC and DIP
DIP是指高層模塊不應(yīng)該依賴低層模塊而都應(yīng)該依賴于抽象。
IOC是用來提供抽象,改變控制。IOC提供了一些方式來實現(xiàn)DIP。如果想讓高層模塊獨立于低層模塊,你需要反轉(zhuǎn)控制才能使低層模塊不去控制接口并創(chuàng)建對象。 最終IOC提供了控制反轉(zhuǎn)的一些方式。
Q93. 什么是Dependency Injection (DI,依賴注入)?
Ans. DI 是一種軟件設(shè)計模式,用來允許我們開發(fā)松耦合代碼。DI是一種很好的方式去減少軟件模塊之間的緊耦合關(guān)心。DI幫助更好的去管理軟件中的功能更新和復(fù)雜度。DI的目的是讓代碼可維護。
依賴注入模式使用構(gòu)造器對對象初始化并提供需要的依賴給對象,也就意味著允許你從類外部注入一個依賴項。
例如,假設(shè)你的客戶端類需要使用一個服務(wù)類組件,那么你能做的就是讓你的客戶知道一類IService接口而不是服務(wù)類。這樣,你就可以隨時改變Service類的實現(xiàn)而不會中斷已經(jīng)部署的代碼。
Q94. 什么是Service Locator(服務(wù)定位器)?
Ans. Service Locator 是一種軟件設(shè)計模式,使得我們可以開發(fā)松耦合的代碼。
它實現(xiàn)了DIP準(zhǔn)則,它很容易與現(xiàn)有代碼一起使用使,因為它可以使整體設(shè)計變得寬松而不需要強制更改公共的接口。
Service Locator模式引入了一個locator(定位器)的對象,該對象用來解決依賴,意味著通過在類中引用該定位器對象就可以解決類的依賴項。
來看一個具體的實例:
public interface IService {
void Serve();
}
public class Service: IService {
public void Serve() {
Console.WriteLine("Service Called");
//To Do: Some Stuff
}
}
public static class LocateService {
public static IService _Service {
get;
set;
}
public static IService GetService() {
if (_Service == null) _Service = new Service();
return _Service;
}
}
public class Client {
private IService _service;
public Client() {
this._service = LocateService.GetService();
}
public void Start() {
Console.WriteLine("Service Started");
this._service.Serve();
//To Do: Some Stuff
}
}
class Program {
static void Main(string[] args) {
var client = new Client();
client.Start();
Console.ReadKey();
}
}
Q95. 有哪幾種方式實現(xiàn)依賴注入?
Ans. 主要有以下三種方式:
** Constructor Injection (構(gòu)造函數(shù)注入)**
這是最常用的注入方式。當(dāng)實例化類的時候通過給類的構(gòu)造函數(shù)提供依賴項來實現(xiàn)依賴注入。注入的依賴可以在類的任何地方直接使用。適用于類需要一個或多個依賴時。
public interface IService {
void Serve();
}
public class Service: IService {
public void Serve() {
Console.WriteLine("Service Called");
}
}
public class Client {
private IService _service;
public Client(IService service) {
this._service = service;
}
public void Start() {
Console.WriteLine("Service Started");
this._service.Serve();
//To Do: Some Stuff
}
}
//Builder
class Program {
static void Main(string[] args) {
Client client = new Client(new Service());
client.Start();
Console.ReadKey();
}
}
Property Injection(屬性注入)
適用于類需要可選的依賴時,或者需要可交換的實現(xiàn)時,比如Log4Net。
在使用時需要Null check。
這種方式不需要增加或修改構(gòu)造函數(shù)。
public class Client {
private IService _service;
public IService Service {
set {
this._service = value;
}
}
public void Start() {
Console.WriteLine("Service Started");
this._service.Serve();
//To Do: Some Stuff
}
}
//Builder
class Program {
static void Main(string[] args) {
Client client = new Client();
client.Service = new Service();
client.Start();
Console.ReadKey();
}
}
Method Injection(方法注入)
這種方式注入依賴到單一的方法,改依賴僅僅被注入的方法使用。
適用于整個類不需要依賴項,而僅僅某個方法需要。
public class Client {
private IService _service;
public void Start(IService service) {
this._service = service;
Console.WriteLine("Service Started");
this._service.Serve();
//To Do: Some Stuff
}
}
//Builder
class Program {
static void Main(string[] args) {
Client client = new Client();
client.Start(new Service());
Console.ReadKey();
}
}
Q96. 依賴注入的好處是什么?
Ans. 主要有以下好處:
- 減少類間耦合
- 增加代碼重用
- 提高代碼可維護性
- 利于應(yīng)用程序測試
Q97. 什么是IOC或DI容器?
Ans. IOC和DI描述的是同一個設(shè)計模式,通常可以交互使用。
因此有人說IOC容器,有人說DI容器,其實它們都指的是同一個東西,所以不要被術(shù)語迷惑。
一個DI容器是一個機制用來創(chuàng)建依賴并當(dāng)需要依賴的時候自動注入。當(dāng)需要依賴時它自動基于請求創(chuàng)建對象并注入。DI容器用一種簡單容易的方式幫助我們管理應(yīng)用程序的依賴。
我們也可以不使用DI容器來管理依賴,但是這樣我們需要做更多的工作來讓其支持可配置和可管理。
Q98. 有哪些流行的DI容器?
Ans. 現(xiàn)在,有很多不錯的DI容器適用于.net。
列舉如下:
Castle Windsor
- 基于 Castle MicroKernel
- 詳細(xì)的文檔
- 使用者多
- Understands Decorator(理解裝飾器)
- Typed factories(類型工廠)
- Commercial support available(官方支持)
Spring.NET
- INTERCEPTION(攔截)
- Comprehensive documentation(全部文檔)
- Commercial support available(官方支持)
Autofac
- Easy to learn API(易于學(xué)習(xí)的API)
- second-generation DI Container(第二代DI容器)
- Commercial support available(官方支持)
Unity
- INTERCEPTION(攔截)
- Good documentation(文檔良好)
- Consistent API(一致的API)
Ninject
- Easy to learn API(易于學(xué)習(xí)的API)
- Second-generation DI Container(第二代DI容器)
Q99.什么是Test Driven Development (TDD,測試驅(qū)動開發(fā))?
Ans. TDD是一個開發(fā)原則,在寫代碼之前先寫測試。
測試驅(qū)動應(yīng)用程序的設(shè)計和開發(fā)周期。
在所有的測試通過之前,不能簽入代碼。
Q100. ASP.NET MVC中有哪些常用的單元測試工具?
Ans. ASP.NET MVC被設(shè)計為可測試的,而不需要依賴IIS、數(shù)據(jù)庫或額外的類。
以下是比較流行的測試工具:
? NUnit - NUnit是 Microsoft .NET上比較流行的單元測試框架。它的語法相對簡單易用。它提供了跑單元測試的GUI和命令行工具。NUnit提供有NuGet包供下載使用。
? xUnit.NET - xUnit.NET提供了一種自動化運行單元測試的方式。它簡單、易于擴展、語法清晰。
? Ninject 2 - Ninject提供連接應(yīng)用程序中類的方式。
? Moq - Moq提供了一種在測試期間模擬類和接口的機制。