二.相依性注入(DI)

在第一天有建立了相關的Service及Controller,但你會發現在建構式裡都需要new一個實體物件,但彼此的相依性太重,Controller相依於Service,而Service又相依於UnitOfWork

此章節將會介紹如何透過DI來降低它的相依性。

ProductController.cs
/// <summary>
/// Public constructor to initialize product service instance
/// </summary>
public ProductController()
{
    _productServices =new ProductServices();
}
ProductServices.cs
/// <summary>
/// Public constructor.
/// </summary>
public ProductServices()
{
    _unitOfWork = new UnitOfWork();
}

加入DI套件

切換到WebApi專案

nuget

Unity是由微軟所推出的DI套件

  • 加入 Unity.mvc

  • 加入 Unity.webapi

設定UnityConfig

切至App_Start資料夾

註冊我們需要注入的物件

  • ProductServices
  • UnitOfWork
UnityConfig.cs
using BusinessServices;
using DataModel;
using Microsoft.Practices.Unity;
using System.Web.Http;
using Unity.WebApi;

namespace WebApi
{
    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = BuildUnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers

            // e.g. container.RegisterType<ITestService, TestService>();

            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers

            // e.g. container.RegisterType<ITestService, TestService>();             
            /*
            HierarchicalLifetimeManager的用途:
                Unity中有一個在管理生命週期的物件叫「ContainerControlledLifetimeManager」,他都會回傳你由`Reslolve`或`ResolveAll`方法所註冊的物件或Type的同一個物件至各自的Class。
                但是他們各自有一個子容器,不會共用一個父容器,所以子容器與父容器會有不同的生命週期。
            */
            container
                .RegisterType<IProductServices, ProductServices>()
                .RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());

            return container;
        }
    }
}

註冊Unity

打開Global.asax

namespace WebApi
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            ...以下省略
        }
    }
}

將PdoructController改為DI的方式

namespace WebApi.Controllers
{
    public class ProductController : ApiController
    {

        private readonly IProductServices _productServices;

        #region Public Constructor

        /********  未加入DI的版本********************
        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController()
        {
            _productServices = new ProductServices();
        }
        ********************************************/

        /// <summary>
        /// Public constructor to initialize product service instance
        /// </summary>
        public ProductController(IProductServices productServices)
        {
            _productServices = productServices;
        }

        #endregion
    }

    ...以下省略
}

編譯後,就可立即感受到DI的便利了。

將ProductServices改為DI的方式

同樣的方式,將原本new物件的地方,改由建構式注入

ProductServices.cs
namespace BusinessServices
{
    /// <summary>
    /// Offers services for product specific CRUD operations
    /// </summary>
    public class ProductServices : IProductServices
    {
        private readonly UnitOfWork _unitOfWork;

        /********  未加入DI的版本 ********************
         /// <summary>
         /// Public constructor.
         /// </summary>
         public ProductServices()
         {
             _unitOfWork = new UnitOfWork();
         }
         *******************************************/

        /// <summary>
        /// Public constructor.
        /// </summary>
        public ProductServices(UnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }
    }
}

results matching ""

    No results matching ""