美文网首页
asp.net-mvc中使用IOC容器创建控制器实例

asp.net-mvc中使用IOC容器创建控制器实例

作者: 浅谈码生活 | 来源:发表于2020-12-07 10:02 被阅读0次

1.)在使用IOC之前,先谈谈什么是IOC?
IOC是Inversion of Control的缩写-“控制反转”。

解耦图.png
通过上图,由于引进了中间位置的第三方,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合的关系,所有的对象都由容器进行管理,这样也可以看出对象A获得依赖对象B的过程,由主动变成被动-(控制反转)

2.)如何通过IOC容器创建实例?
IOC容器是通过反射进行创建实例,而对IOC的具体实现的框架有多种,当然也可以自己封装一套自己的容器,而今天主要介绍的是Unity容器。
通过NuGet导入Unity包:


Unity包.png

创建一个Unity容器:
IUnityContainer unityContainer = new UnityContainer();
注册对象:
//IPhone-抽象
//AndroidPhone-具体实现
unityContainer.RegisterType<IPhone, AndroidPhone>();
获取对象的实例:
IPhone phone = unityContainer.Resolve<IPhone>();

3.)Unity生命周期
默认瞬时生命周期:每次返回都是一个新的对象。

container.RegisterType<AbstractPad, ApplePad>(new TransientLifetimeManager());
AbstractPad Pad1 = container.Resolve<AbstractPad>();
AbstractPad Pad2 = container.Resolve<AbstractPad>();
Console.WriteLine(object.ReferenceEquals(Pad1, Pad2));

单例生命周期:每次返回都是同一个对象。

container.RegisterType<AbstractPad, ApplePad>(new SingletonLifetimeManager());
AbstractPad pad1 = container.Resolve<AbstractPad>();
AbstractPad pad2 = container.Resolve<AbstractPad>();
Console.WriteLine(object.ReferenceEquals(pad1, pad2));

线程单例生命周期:同一个线程就只有一个实例,不同线程就是不同实例。

container.RegisterType<AbstractPad, ApplePad>(new PerThreadLifetimeManager());
AbstractPad pad1 = null;
AbstractPad pad2 = null;
AbstractPad pad3 = null;
Action act1 = new Action(() =>
{
    pad1 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad1由线程id={Thread.CurrentThread.ManagedThreadId}");
});
var result1 = act1.BeginInvoke(null, null);

Action act2 = new Action(() =>
{
    pad2 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad2由线程id={Thread.CurrentThread.ManagedThreadId}");
});
var result2 = act2.BeginInvoke(t =>
{
    pad3 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad3由线程id={Thread.CurrentThread.ManagedThreadId}");
    Console.WriteLine($"object.ReferenceEquals(pad2, pad3)={object.ReferenceEquals(pad2, pad3)}");
}, null);
act1.EndInvoke(result1);
act2.EndInvoke(result2);
Console.WriteLine($"object.ReferenceEquals(pad1, pad2)={object.ReferenceEquals(pad1, pad2)}");

4.)Unity通过配置文件进行注册
配置文件代码:

 <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
    <containers>
      <container name="testContainer1">
        <!--支持AOP-->
        <extension type="Interception"/>
        <register type="IOC.Interface.IPhone,IOC.Interface" mapTo="IOC.Service.ApplePhone, IOC.Service"/>
        <!--是dll名称,不是命名空间-->
        <!--接口多个实现别名获取-->
        <register type="IOC.Interface.IPhone,IOC.Interface" mapTo="IOC.Service.AndroidPhone, IOC.Service" name="Android">
          <!--别名--> 
          <interceptor type="InterfaceInterceptor"/>
          <interceptionBehavior type="Common.AOP.LogBeforeBehavior, Common"/>
          <interceptionBehavior type="Common.AOP.LogAfterBehavior, Common"/>
          <interceptionBehavior type="Common.AOP.ParameterCheckBehavior, Common"/>
          <lifetime type="transient" /> 
        </register>
        <register type="IOC.Interface.IMicrophone, IOC.Interface" mapTo="IOC.Service.Microphone, IOC.Service"/>
        <register type="IOC.Interface.IHeadphone, IOC.Interface" mapTo="IOC.Service.Headphone, IOC.Service"/>
        <register type="IOC.Interface.IPower, IOC.Interface" mapTo="IOC.Service.Power, IOC.Service"/>
        <register type="IOC.Interface.AbstractPad, IOC.Interface" mapTo="IOC.Service.ApplePad, IOC.Service"/>
        <register type="IOC.IDAL.IBaseDAL, IOC.IDAL" mapTo="IOC.DAL.BaseDAL, IOC.DAL"/>
        <register type="IOC.IBLL.IBaseBll, IOC.IBLL" mapTo="IOC.BLL.BaseBll, IOC.BLL">
          <constructor>
            <param name="baseDAL" type="IOC.IDAL.IBaseDAL, IOC.IDAL"  />
            <param name="id" type="System.Int32" value="3" />
          </constructor>
        </register>
        <register type="IOC.IDAL.IDBContext`1, IOC.IDAL" mapTo="IOC.DAL.DBContextDAL`1, IOC.DAL"/>
      </container>
    </containers>
  </unity>

前台创建实例:

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);
IUnityContainer container = new UnityContainer();
section.Configure(container, "testContainer1");
//创建实例
IPhone phone = container.Resolve<IPhone>("Android");

5.)基于Unity扩展AOP:AOP面向切面编程应用场景

在有了以上了解之后,在去通过IOC容器创建控制器实例便清晰了
有参控制器,通过容器创建并构造函数依赖注入

 public class ThirdController : Controller
{
          public IUserService _iUserService = null;
          public ICompanyService _iCompanyService = null;

          public ThirdController(IUserService userService, ICompanyService companyService)
          { 
                     _iUserService = userService;
                     _iCompanyService = companyService; 
           }
}

1.)重写“默认控制器工厂”

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
   {
        //要通过容器来创建控制器实例  得先得到容器
        //1. 获取容器,并将后期依赖进行注册
        IUnityContainer container = DIFactory.GetContainer();
        //2.通过容器创建控制器实例,根据实例类型,查找实例构造函数所需要的依赖项,
        //通过容器内的对象进行注入,若在容器内无法找到则无法实例该对象
        return (IController)container.Resolve(t: controllerType);       
    }
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        return base.CreateController(requestContext, controllerName);
    }
}

2.)替换“默认控制器工厂”
Global.asax

  //用自定义的控制器工厂替换掉MVC框架中默认的控制器工厂
  ControllerBuilder.Current.SetControllerFactory(new RichardControllerFactory());

经过上述的过程,

相关文章

  • asp.net-mvc中使用IOC容器创建控制器实例

    1.)在使用IOC之前,先谈谈什么是IOC?IOC是Inversion of Control的缩写-“控制反转”。...

  • Spring的常用类的作用

    ClassPathXmlApplicationContext 核心在创建IoC容器对象,用容器获取bean实例,有...

  • 2.IOC原理分析

    要想使用Spring IOC,必须要创建Spring IOC容器 ? 什么是IOC容器? 所谓的IoC容器就是指的...

  • 7、IoC/DI学习

    1、概念 IoC就是控制反转,就是具有依赖注入功能的容器,是可以创建对象的容器,IOC容器负责实例化、定位、配置应...

  • IoC容器的使用

    IoC容器的实例化 要想使用Spring容器,就必须提供一些配置让它实例化。 Spring提供了两种IoC容器的实...

  • 实例化Bean

    Spring IoC容器需要根据Bean定义里的配置元数据使用反射机制来创建Bean。在Spring IoC容器中...

  • IoC(二)容器基本原理

    2.2.1 IoC容器的概念 IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化、定位、配置应用程序中的...

  • spring学习3(基本XML配置)

    配置Bean 基本配置 class:bean的全类名,通过反射方式在ioc容器中创建bean的实例 id:标识容器...

  • Spring IOC

    IOC (Inversion of control)控制反转。将对象创建(实例化、管理)的控制权交给了IOC容器...

  • Spring Ioc 容器原理

    IOC容器的概念 IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些...

网友评论

      本文标题:asp.net-mvc中使用IOC容器创建控制器实例

      本文链接:https://www.haomeiwen.com/subject/mvmowktx.html