1、常規寫法,難道我們每次都new一個服務,如下麵的UserService和CompanyService然後調用服務的Find方法去操作,為什麼我們不讓UserService和CompanyService服務註入進來呢? 2、我們想要的實際效果是MVC請求進來的時候,實例化控制器的時候,就把User ...
1、常規寫法,難道我們每次都new一個服務,如下麵的UserService和CompanyService然後調用服務的Find方法去操作,為什麼我們不讓UserService和CompanyService服務註入進來呢?
public ActionResult Index()
{
DbContext context = new DbContext();
IUserService userService = new UserService(context);
User user = userService.Find<User>(2);
return View(user);
}
public ActionResult Index2() { DbContext context = new DbContext(); ICompanyService companyService = new CompanyService(context);
Company company = companyService.Find<Company>(2);
return View(company);
}
2、我們想要的實際效果是MVC請求進來的時候,實例化控制器的時候,就把UserService和CompanyService服務註入進來,但是下麵的帶參數的控制器構造函數TestController(IUserService userService, ICompanyService companyService)MVC是實例化不了的,MVC只能實例化不帶參數的構造函數TestController()
public class TestController : Controller
{
private IUserService _iUserService = null;
private ICompanyService _iCompanyService = null;
/// <summary>
/// 構造函數註入---控制器得是由容器來實例化
/// </summary>
/// <param name="userService"></param>
/// <param name="companyService"></param>
public TestController(IUserService userService, ICompanyService companyService)
{
this._iUserService = userService;
this._iCompanyService = companyService;
}
}
public ActionResult Index() { DbContext context = new DbContext(); IUserService userService = this._iUserService; User user = userService.Find<User>(2); return View(user); }
public ActionResult Index2() { DbContext context = new DbContext(); ICompanyService companyService = this._iCompanyService;
Company company = companyService.Find<Company>(2);
return View(company);
}
3、在“1、看源碼MVC如何實例化控制器”中提到MVC實例化控制器使用的是ControllerBuilder.GetControllerFactory()得到一個DefaultControllerFactory工廠,然後用工廠的CreateController方法利用反射去創建Controller實例,那麼我們可以把工廠換成自己實現的自定義工廠不就可以了嗎,ControllerBuilder還有個SetControllerFactory方法,自定義的控制器工廠CustomControllerFactory繼承DefaultControllerFactory,微軟的特點是virtual和abstract都是讓我們來擴展的,那麼我們覆寫GetControllerInstance方法,在GetControllerInstance方法里去構建容器
public class CustomControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
IUnityContainer container = DIFactory.GetContainer();
//return base.GetControllerInstance(requestContext, controllerType);
return (IController)container.Resolve(controllerType);
}
}
4、在Application_Start中指定自定義的控制器工廠
public class MvcApplication : System.Web.HttpApplication
{protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();//註冊區域
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//註冊全局的Filter
RouteConfig.RegisterRoutes(RouteTable.Routes);//註冊路由
BundleConfig.RegisterBundles(BundleTable.Bundles);//合併壓縮 ,打包工具 Combres
ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());//設置自定義的控制器工廠
}
}
5、依賴註入
public class DIFactory
{
public static IUnityContainer GetContainer()
{
IUnityContainer container = null;
//container.RegisterType
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
container = new UnityContainer();
section.Configure(container, "MyContainer");
return container;
}
}
6、進行Unity配置
<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="MyContainer">
<extension type="Interception"/>
<register type="System.Data.Entity.DbContext, EntityFramework" mapTo="SchoolManager.EF.Model.SchoolDBEntities, SchoolManager.EF.Model"/>
<register type="SchoolManager.Bussiness.Interface.ICompanyService,SchoolManager.Bussiness.Interface" mapTo="SchoolManager.Bussiness.Service.CompanyService, SchoolManager.Bussiness.Service"/>
<register type="SchoolManager.Bussiness.Interface.IUserService,SchoolManager.Bussiness.Interface" mapTo="SchoolManager.Bussiness.Service.UserService, SchoolManager.Bussiness.Service"/>
</container>
</containers>
</unity>
</configuration>