zoukankan      html  css  js  c++  java
  • ASP.NET MVC Unity实现依赖注入

    这两天看Spring.net,看到了控制反转依赖注入,因为公司项目没有使用到spring.net,所以想学学关于ASP.NET MVC中的依赖注入,通过学习发现有两种方式,第一种就是微软自带Unity,还一种是一个比较简单的框架Ninject,我觉得应该差不多,目前只试了Unity,所以先来说Unity

    Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入。Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题。构建一个成功应用程序的关键是实现非常松散的耦合设计。松散耦合的应用程序更灵活,更易于维护。这样的程序也更容易在开发期间进行测试。你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件。例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是否被授权执行更新。依赖注入技术,可确保客户类正确实例化和填充所有这些对象,尤其是在依赖可能是抽象的 。

    原文地址:http://www.cnblogs.com/sixiangqimeng/p/3571849.html                       

    示例1:根据接口依赖创建类

     

    上边简单介绍了Unity的API。如果在没有注册的情况下Resolve一个类型会发生什么呢?

    假设我们需要对日志进行处理。我们先声明一个接口ILogger:

     

      public interface ILogger
    {
    void Write(string log);

    }

     

    我们可以有多种方法实现这个接口,我们假设希望写日志到文件中:

      public class FileLogger:ILogger
    {

    #region ILogger Members

    public void Write(string log)
    {
    Console.WriteLine("Write log in file.");
    }

    #endregion
    }

    我们在实际生活中对数据库的选择也是多种多样的。我们创建一个数据库的基类:

    public class Database
    {
    }

    创建一个派生类:

    public class CustomerDatabase : Database
    {
    private ILogger _logger;
    public CustomerDatabase(ILogger logger)
    {
    _logger = logger;
    }
    }

    注意它的构造器的参数是ILogger类型。首先我们要创建一个Unity 容器:

    UnityContainer container = new UnityContainer();

    接下来我们需要在容器中注册一种类型,它是一个类型的映射,接口类型是ILogger,我希望返回的类型是FileLogger:

    container.RegisterType<ILogger, FileLogger>();

    然后我们使用Resolve 方法:

    Database database = container.Resolve<CustomerDatabase>();

    经过调试我们可以发现,如果在容器中没有注册的类型。执行Resolv方法后,Unity尝试创建该类型,会执行该类的构造器。最后database变量的类型就是CustomerDatabase,而且它的私有字段ILogger的当前实例也为FileLogger。

    示例2:类型映射

     

    我们希望返回一个日志类的实例,无论它是哪个实现类。我们可以直接在Resolve的类型中指定类型为接口ILogger:

    UnityContainer container = new UnityContainer();
    container.RegisterType<ILogger, FileLogger>();
    ILogger logger = container.Resolve<ILogger>();

    每一次 container都会给我们返回一个新的logger实例。

    示例3:单例模式的注册

    如果我们想告诉Unity,我们想控制生命周期,我们想用单例模式。RegisterType方法包含一个重载,将使用LifetimeManager。每次我们在想获得到database实例时,unity总是会返回第一次我创建的CustomerDatabase。

    UnityContainer container = new UnityContainer();
    container.RegisterType<Database, CustomerDatabase>
    (new ContainerControlledLifetimeManager());

    示例4:注册时附带key

    在我们向容器里注册时,可以附带一个string 类型的Key值。

    UnityContainer container = new UnityContainer();
    container.RegisterType<Database, SQLDatabase>("SQL");
    container.RegisterType<Database, ORACLEDatabase>("ORACLE");
    IEnumerable<Database> databases = container.ResolveAll<Database>();
    Database database = container.Resolve<Database>("SQL");

    我们分别向容器中注册了名为“SQL“和”ORACLE“的Database。当我们使用ResolverAll方法是。容器会返回容器中所有类型为Database的类。

    这时我们如果仅仅想回去SQL的实例,我们可以使用container.Resolve<Database>("SQL");

     

    //================================================================================================================================================//

    上面的项目是网上借鉴的,下面自己写了一个项目实现依赖注入

    //================================================================================================================================================//

    这段是对封装的容器做进一步处理

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.Mvc;
    using Microsoft.Practices.Unity;
    
    namespace Unity.Mvc3
    {
        public class UnityDependencyResolver : IDependencyResolver
        {
            private const string HttpContextKey = "perRequestContainer";
    
            private readonly IUnityContainer _container;
    
            public UnityDependencyResolver(IUnityContainer container)
            {
                _container = container;
            }
    
            public object GetService(Type serviceType)
            {
                if (typeof(IController).IsAssignableFrom(serviceType))
                {
                    return ChildContainer.Resolve(serviceType);
                }
    
                return IsRegistered(serviceType) ? ChildContainer.Resolve(serviceType) : null;            
            }
    
            public IEnumerable<object> GetServices(Type serviceType)
            {
                if (IsRegistered(serviceType))
                {
                    yield return ChildContainer.Resolve(serviceType);
                }
    
                foreach (var service in ChildContainer.ResolveAll(serviceType))
                {
                    yield return service;
                }
            }
    
            protected IUnityContainer ChildContainer
            {
                get
                {
                    var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer;
    
                    if (childContainer == null)
                    {
                        HttpContext.Current.Items[HttpContextKey] = childContainer = _container.CreateChildContainer();
                    }
    
                    return childContainer;
                }
            }        
    
            public static void DisposeOfChildContainer()
            {
                var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer;
    
                if (childContainer != null)
                {
                    childContainer.Dispose();
                }
            }
    
            private bool IsRegistered(Type typeToCheck)
            {
                var isRegistered = true;
    
                if (typeToCheck.IsInterface || typeToCheck.IsAbstract)
                {
                    isRegistered = ChildContainer.IsRegistered(typeToCheck);
    
                    if (!isRegistered && typeToCheck.IsGenericType)
                    {
                        var openGenericType = typeToCheck.GetGenericTypeDefinition();
    
                        isRegistered = ChildContainer.IsRegistered(openGenericType);
                    }
                }
    
                return isRegistered;
            }
        }    
    }
    using System;
    using System.Diagnostics;
    
    namespace Unity.Mvc3.Example.Models
    {
        public class ExampleContext : IExampleContext, IDisposable
        {
            public ExampleContext()
            {
                Debug.WriteLine("ExampleContext Constructor");
            }
    
            public string GetMessage()
            {
                Debug.WriteLine("ExampleContext GetMessage");
                return "A message from the ExampleContext";
            }
    
            public void Dispose()
            {
                Debug.WriteLine("ExampleContext Dispose");
            }
        }
    }
    namespace Unity.Mvc3.Example.Models
    {
        public interface IExampleContext
        {
            string GetMessage();
        }
    }
    namespace Unity.Mvc3.Example.Models
    {
        public class LowerCaseService : ILowerCaseService
        {
            private readonly IExampleContext _context;
    
            public LowerCaseService(IExampleContext context)
            {
                _context = context;
            }
    
            public string GetMessage()
            {
                return _context.GetMessage().ToLower();
            }
        }
    }
    
    
    namespace Unity.Mvc3.Example.Models
    {
        public interface ILowerCaseService
        {
            string GetMessage();
        }
    }
    namespace Unity.Mvc3.Example.Models
    {
        public class UpperCaseService : IUpperCaseService
        {
            private readonly IExampleContext _context;
    
            public UpperCaseService(IExampleContext context)
            {
                _context = context;
            }
    
            public string GetMessage()
            {
                return _context.GetMessage().ToUpper();
            }
        }
    }
    
    namespace Unity.Mvc3.Example.Models
    {
        public interface IUpperCaseService
        {
            string GetMessage();
        }
    }

     原文地址:http://www.cnblogs.com/sixiangqimeng/p/3571849.html            

    using System.Web.Mvc;
    using Unity.Mvc3.Example.Models;
    
    namespace Unity.Mvc3.Example.Controllers
    {
        public class HomeController : Controller
        {
            private readonly IUpperCaseService _upperCaseService;
            private readonly ILowerCaseService _lowerCaseService;
    
            public HomeController(IUpperCaseService upperCaseService, ILowerCaseService lowerCaseService)
            {
                _upperCaseService = upperCaseService;
                _lowerCaseService = lowerCaseService;
            }
    
            public ActionResult Index()
            {
                ViewBag.Message1 = _upperCaseService.GetMessage();
    
                ViewBag.Message2 = _lowerCaseService.GetMessage();
    
                return View();
            }
    
            public ActionResult About()
            {
                ViewBag.Message = _upperCaseService.GetMessage();
    
                return View();
            }
        }
    }
       protected void Application_Start()
            {
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
    
                Bootstrapper.Initialise();
            }

     

  • 相关阅读:
    检测主机存活
    centos7 安装python3
    zbb20180103 git 配置用户名和邮箱
    zbb20171215 git 版本回退
    zbb20171215 bootstrap model 模态框
    zbb20171215 MyBatis报错: Parameter '*' not found. Available parameters are [1, 0, param1, param2]
    zbb20171215 thymeleaf th:attr
    zbb20171215ztree ztree出现$.fn.zTree is undefined错误的解决办法
    zbb20171215 bootstrap 日期控件.rar
    zbb20171215 oracle replace 替换单引号
  • 原文地址:https://www.cnblogs.com/sixiangqimeng/p/3571849.html
Copyright © 2011-2022 走看看