2、MVC+IOC容器+ORM结合

0
13

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>

<

发布回复

请输入评论!
请输入你的名字