欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

IOC的理解,整合AOP,解耦对Service层和Dal层的依赖

程序员文章站 2022-05-29 13:32:05
DIP依赖倒置原则:系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖依赖抽象,而不是细节 贯彻依赖倒置原则,左边能抽象,右边实例化的时候不能直接用抽象,所以需要借助一个第三方 高层本来是依赖低层,但是可以通过工厂(容器)来决定细节,去掉了对低层的依赖 IOC控制反转:把高层对低层的依赖, ......


 dip依赖倒置原则:系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖
依赖抽象,而不是细节

 贯彻依赖倒置原则,左边能抽象,右边实例化的时候不能直接用抽象,所以需要借助一个第三方

 高层本来是依赖低层,但是可以通过工厂(容器)来决定细节,去掉了对低层的依赖
 ioc控制反转:把高层对低层的依赖,转移到第三方决定,避免高层对低层的直接依赖(是一种目的)
那么程序架构就具备良好扩展性和稳定性

di依赖注入:是用来实现ioc的一种手段,
 在构造对象时,可以自动的去初始化,对象需要的对象
构造函数注入 属性注入 方法注入,ioc容器初始化applephone的时候 通过配置文件实例化 属性,方法,构造函数

using microsoft.practices.unity;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using ruanmou.interface;
using system;
using unity.attributes;

namespace ruanmou.service
{
    public class applephone : iphone
    {
        [dependency]//属性注入:不错,但是有对容器的依赖
        public imicrophone imicrophone { get; set; }
        public iheadphone iheadphone { get; set; }
        public ipower ipower { get; set; }

        //[injectionconstructor]
        public applephone()
        {
            console.writeline("{0}构造函数", this.gettype().name);
        }

        //[injectionconstructor]//构造函数注入:最好的,默认找参数最多的构造函数
        public applephone(iheadphone headphone)
        {
            this.iheadphone = headphone;
            console.writeline("{0}带参数构造函数", this.gettype().name);
        }

        public void call()
        {
            console.writeline("{0}打电话", this.gettype().name); 
        }

        [injectionmethod]//方法注入:最不好的,增加一个没有意义的方法,破坏封装
        public void init1234(ipower power)
        {
            this.ipower = power;
        }
    }
}

 

不管是构造对象,还是注入对象,这里都是靠反射做到的

有了依赖注入,才可能做到无限层级的依赖抽象,才能做到控制反转

 

ioc unity容器 可以通过代码注册或配置文件注册接口对应实现类,实现了不依赖具体,可以对对象全局单例,线程单例

例子1

service业务逻辑层升级,在原有1.0的基础上添加一些功能,使用配置文件注册

      <container name="testcontainer1">
        <register type="ruanmou.interface.iphone,ruanmou.interface" mapto="ruanmou.service.applephone, ruanmou.service"/>
        <register type="ruanmou.interface.iphone,ruanmou.interface" mapto="ruanmou.service.androidphone, ruanmou.service" name="android"/>
        <register type="ruanmou.interface.imicrophone, ruanmou.interface" mapto="ruanmou.service.microphone, ruanmou.service"/>
        <register type="ruanmou.interface.iheadphone, ruanmou.interface" mapto="ruanmou.service.headphone, ruanmou.service"/>
        <register type="ruanmou.interface.ipower, ruanmou.interface" mapto="ruanmou.service.power, ruanmou.service"/>
        <register type="ruanmou.idal.ibasedal, ruanmou.idal" mapto="ruamou.dal.basedal, ruamou.dal"/>
      </container>

      <container name="testcontainer">
        <register type="ruanmou.interface.iphone,ruanmou.interface" mapto="ruanmou.service.androidphone, ruanmou.service.extend"/>
        <register type="ruanmou.interface.iphone,ruanmou.interface" mapto="ruanmou.service.androidphone, ruanmou.service.extend" name="android"/>
        <register type="ruanmou.interface.imicrophone, ruanmou.interface" mapto="ruanmou.service.microphone, ruanmou.service.extend"/>
        <register type="ruanmou.interface.iheadphone, ruanmou.interface" mapto="ruanmou.service.headphone, ruanmou.service.extend"/>
        <register type="ruanmou.interface.ipower, ruanmou.interface" mapto="ruanmou.service.power, ruanmou.service.extend"/>
        <register type="ruanmou.idal.ibasedal, ruanmou.idal" mapto="ruamou.dal.basedal, ruamou.dal"/>
      </container>

只需要把服务2.0的类库(实现1.0的原有接口)dll拿过来即可使用,代码不做任何修改

例子2 业务扩展,新加功能

应该是加几个接口和实现类的映射,就可以解决了。

例子3 实现aop

方法需要加日志,加异常管理,可以不修改原有代码,直接新加异常管理类等的类库,在unity配置文件添加aop配置节点即可实现

IOC的理解,整合AOP,解耦对Service层和Dal层的依赖

配置文件配置,

      <container name="testcontaineraop">
        <extension type="interception"/>
        <register type="ruanmou.interface.iphone,ruanmou.interface" mapto="ruanmou.service.androidphone, ruanmou.service.extend">
          <interceptor type="interfaceinterceptor"/>
          <interceptionbehavior type="ruanmou.framework.aop.authorizebehavior, ruanmou.framework"/>
          <interceptionbehavior type="ruanmou.framework.aop.smsbehavior, ruanmou.framework"/>
          <interceptionbehavior type="ruanmou.framework.aop.exceptionloggingbehavior, ruanmou.framework"/>
          <interceptionbehavior type="ruanmou.framework.aop.cachingbehavior, ruanmou.framework"/>
          <interceptionbehavior type="ruanmou.framework.aop.logbeforebehavior, ruanmou.framework"/>
          <interceptionbehavior type="ruanmou.framework.aop.parametercheckbehavior, ruanmou.framework"/>
          <interceptionbehavior type="ruanmou.framework.aop.logafterbehavior, ruanmou.framework"/>
        </register>
        <register type="ruanmou.interface.iphone,ruanmou.interface" mapto="ruanmou.service.androidphone, ruanmou.service.extend" name="android"/>
        <register type="ruanmou.interface.imicrophone, ruanmou.interface" mapto="ruanmou.service.microphone, ruanmou.service.extend"/>
        <register type="ruanmou.interface.iheadphone, ruanmou.interface" mapto="ruanmou.service.headphone, ruanmou.service.extend"/>
        <register type="ruanmou.interface.ipower, ruanmou.interface" mapto="ruanmou.service.power, ruanmou.service.extend"/>
        <register type="ruanmou.idal.ibasedal, ruanmou.idal" mapto="ruamou.dal.basedal, ruamou.dal">
        </register>
      </container>

 贴一个异常处理的aop例子代码

namespace ruanmou.framework.aop
{
    public class exceptionloggingbehavior : iinterceptionbehavior
    {
        public ienumerable<type> getrequiredinterfaces()
        {
            return type.emptytypes;
        }

        public imethodreturn invoke(imethodinvocation input, getnextinterceptionbehaviordelegate getnext)
        {
            imethodreturn methodreturn = getnext()(input, getnext);

            console.writeline("exceptionloggingbehavior");
            if (methodreturn.exception == null)
            {
                console.writeline("无异常");
            }
            else
            {
                console.writeline($"异常:{methodreturn.exception.message}");
            }
            return methodreturn;
        }

        public bool willexecute
        {
            get { return true; }
        }
    }
}

 

例子4 数据访问层的替换,因为已经不依赖具体实现,把配置文件的接口对应的数据访问层实现类替换即可,配置文件格式为interface map 实现类

数据访问层的封装公共增删改查,unity 管理 ef dbcontext,保持全局或线程单例还没有看到,最近在学内存管理和.net垃圾回收