zoukankan      html  css  js  c++  java
  • ASP.NET MVC Tip: Dependency Injection with StructureMap (摘抄)

    In this tip, I demonstrate how you can use the dependency injection with StructureMap within an MVC application. StructureMap is an open source Dependency Injection framework for the .NET platform and has been in use since 2004 .StructureMap supports both setter and constructor injection and also offers testing and diagnostic features such as logging, tracing and wiring of mock objects. For download and more details visithttp://structuremap.sourceforge.net/default.htm. Jeremy D Miller’s (Creator of StructureMap) blog is a great learning resource for StructureMap and good object oriented programming thoughts.

     

    If you are not familiar with Dependency Injection (DI) and Inversion of Control (IoC), read Martin Fowler’s article Inversion of Control Containers and the Dependency Injection pattern . A Dependency Injection framework injects the dependencies into a class when the dependencies are needed. Dependency Injection enables looser coupling between classes and their dependencies and can be improve architectural qualities of an object oriented business application.

     

    Dependency Injection provides the following advantages,

     

    1) Enables looser coupling between classes and their dependencies

    2) It provides better testability of an application

    3) It removes the need for clients to know about their dependencies and how to   create them.

    4) It avoid behind the problems of creating factory classes, by moving construction responsibility to a framework.

    5) Improve the architecture quality of an object oriented system. 

     

    In this tip, I show how you can use the StructureMap to perform Dependency Injectionwithin an ASP.NET MVC application.  In this tip, I will show you how to perform constructor injection. Constructor Injection will push dependencies into a concrete class through constructor arguments.

     

    The below code listings show that a controller class and its dependent classes.

     

     

    Listing 1 – CategoryController

     

    public class CategoryController : Controller {

     ICategoryService  _categoryService = null; 

     

     public CategoryController(ICategoryService categoryService) {         

        _categoryService = categoryService;

       }       

     public ActionResult List(int? page) {

      var categories = _categoryService.GetCategories(page ?? 0, 10);

        return View("CategoryList",categories);

      }


     

    Listing 2 – ICategoryService

     

    public interface ICategoryService {

      PagedList<Category> GetCategories(int pageIndex,int pageSize);       

     }

                                   

    Listing 3 – CategoryService

      

    public class CategoryService : ICategoryService  {

     ICategoryRepository _repository = null;       

     public CategoryService(ICategoryRepository repository) {

         _repository = repository;

         if (_repository == null) {

             throw new InvalidOperationException("Repository cannot be null");

            } 

    public PagedList<Category> GetCategories(int pageIndex,int pageSize) {

        return _repository.GetCategories().ToPagedList<Category>(pageIndex, pageSize);

            }

        }

     

    Listing 4 – ICategoryRepository

     

    public interface ICategoryRepository {

          IQueryable<Category> GetCategories();

        }

     

    Listing 5 – CategoryRepository

     

    public class CategoryRepository : ICategoryRepository  {

      DBDataContext _db;

      public CategoryRepository(DBDataContext dataContext) {           

         _db = dataContext;           

       } 

           

     public IQueryable<Category> GetCategories() {

        return from c in _db.Categories

          select new Category {

            ID=c.ID,

            Name=c.Name,

            Description=c.Description,

            CategoryType = c.CategoryType

          }; 

         }

        } 

      

    Depedencies

     

    The CategoryController has a dependency with ICategoryService. The concrete implementation of ICategoryService, i.e. CategoryService has a dependency withICategoryRepository. The concrete implementation of ICategoryRepository, i.e.CategoryRepository has a dependency with DBDataContext. When we calling action methods of Category controller, we need to create objects CategoryService, CategoryRepository and DBDataContext.

     

    The below steps will configure StructureMap to perform constructor injection in our ASP.NET MVC application.

     

    Step 1 – Add reference to StructureMap

     

    Add a reference to StructureMap.dll.

    Download available from http://sourceforge.net/projects/structuremap/

     

    Step 2 – Add StructureMap configuration

     

    using StructureMap;

    using StructureMap.Configuration.DSL;

    using StructureMap.Configuration;

    using StructureMap.Pipeline;

     

    public class DomainRegistry : Registry {

       protected override void configure() {

        ForRequestedType<ICategoryService>()

           .TheDefaultIsConcreteType<CategoryService>(); 

       ForRequestedType<ICategoryRepository>()

          .TheDefaultIsConcreteType<CategoryRepository>(); 

            }

        }

     

    public class DBServiceRegistry:Registry { 

      protected override void configure() { 

         ForRequestedType<DBDataContext >()

          .TheDefaultIs(() => new DBDataContext())

            .CacheBy(InstanceScope.Hybrid); 

            }

        }

     

    The above configuration tells StructureMap to inject CategoryService when there is a request for ICategoryService. And also inject CategoryRepository when there is a request for ICategoryRepository. The CategoryRepository class has a dependency with Linq DataContext DBDataContext. So we configure that create a new instance DBDataContext when there is request for DBDataContext. we are telling the StructureMapConfiguration to make hybrid instance scope. The below are the different type of instance scoping, 

     

       1. PerRequest - The default operation.  A new instance will be created for each request.

       2. Singleton - A single instance will be shared across all requests

       3. ThreadLocal - A single instance will be created for each requesting thread.  Caches the instances with ThreadLocalStorage.

       4. HttpContext - A single instance will be created for each HttpContext.  Caches the instances in the HttpContext.Items collection.

       5. Hybrid - Uses HttpContext storage if it exists, otherwise uses ThreadLocal storage

     

    Step 3 – Register with StructureMap registry

     

    The below code will add instances of DomainRegistry and DBServiceRegistry into StructureMapConfiguration registry.

     

    using StructureMap; 

    public static class Bootstrapper { 

     public static void ConfigureStructureMap() { 

       StructureMapConfiguration.AddRegistry(new DBServiceRegistry());

       StructureMapConfiguration.AddRegistry(new DomainRegistry ());

      }

     }

     

    Step 4 – Controller Factory for StructureMap

     

    using StructureMap; 

    public class StructureMapControllerFactory : DefaultControllerFactory { 

      protected override IController GetControllerInstance(Type controllerType) {

       try {

          return ObjectFactory.GetInstance(controllerType) as Controller;

        }

    catch (StructureMapException) {

         System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());

          throw;

       }

      }

     

     

    The controller factory is responsible for creating controller instances. We extend the built in default controller factory with our own factory for working StructureMap with ASP.NET MVC . 

     

    Step 5 – Modify Global.asax.cs

     

    protected void Application_Start() {

      RegisterRoutes(RouteTable.Routes);

       //Configure StructureMapConfiguration

       Bootstrapper.ConfigureStructureMap();

        //Set current Controller factory as StructureMapControllerFactory

        ControllerBuilder.Current.SetControllerFactory( newmyFinance.Web.Controllers.StructureMapControllerFactory()

       ); 

     }

     

    The above code will set our controller factory and configure StructureMap configuration when our ASP.NET MVC application is started.

     

    Summary

     

    In this tip, I demonstrated how you can use the StructureMap to perform Dependency Injection through constructor injection within an ASP.NET MVC application. One of the greatest advantages of ASP.NET MVC is testability. With a Dependency Injection framework, we can make our ASP.NET MVC application is fully testable and maintainable.

    作者:Jacques Zhu
    出处:http://www.cnblogs.com/Jacques
    本文版权归作者和博客所有,欢迎转载。但未经作者同意,必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

  • 相关阅读:
    小总结
    使用Bind提供域名解析服务(正向解析)
    在虚拟机上的NFS网络文件系统
    在虚拟机上的FTP FTP访问模式(虚拟用户模式)
    在虚拟机上的FTP FTP访问模式(本地用户模式)
    在虚拟机上的FTP,FTP访问模式(匿名)
    在虚拟机上的关于Apache(阿帕奇)(5)基于端口访问网站
    在虚拟机上的关于Apache(阿帕奇)(4)基于域名访问网站
    在虚拟机上的关于Apache(阿帕奇)(3)基于IP访问网站
    在虚拟机上的关于Apache(阿帕奇)(2)开启个人用户主页功能
  • 原文地址:https://www.cnblogs.com/Jacques/p/2171540.html
Copyright © 2011-2022 走看看