zoukankan      html  css  js  c++  java
  • 【进击.NET高级程序员之路】【二】

    一、通过AutoFac实现IOC

    1、使用Nuget引入Autofac包,由于自己是MVC项目,所以引入了三个

    2、创建Autofac的配置

    /// <summary>
            ///  负责调用autofac框架实现业务逻辑层和数据仓储层程序集中的类型对象的创建
            ///  负责创建MVC控制器类的对象(调用控制器中的有参构造函数),接管DefaultControllerFactory的工作
            /// </summary>
            public static void Register()
            {
                #region 逐个注册方法
                ////创建autofac管理注册类的容器实例
                //var builder = new ContainerBuilder();
                ////下面就需要为这个容器注册它可以管理的类型
                ////builder的Register方法可以通过多种方式注册类型,之前在控制台程序里面也演示了好几种方式了。
                //builder.RegisterType<People>().As<IPeople>();
    
                ////builder.RegisterType<DefaultController>().InstancePerDependency();
                ////使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册
                //builder.RegisterControllers(Assembly.GetExecutingAssembly());
                ////生成具体的实例
                //var container = builder.Build();
                ////下面就是使用MVC的扩展 更改了MVC中的注入方式.
                //DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
                #endregion
    
                #region 批量注册方法
    
                //实例化一个autofac的创建容器
                var builder = new ContainerBuilder();
    
                #region 一种注册方式
                //告诉autofac框架,将来要创建的控制器类存放在哪个程序集(CommonFrame.Web)
                Assembly controllerAss = Assembly.Load("CommonFrame.Web");
                builder.RegisterControllers(controllerAss).PropertiesAutowired();//支持构造方式和属性方式方式注入,不加PropertiesAutowired则只支持构造方式
    
                //告诉autofac框架注册Service层所在程序集中的所有类的对象实例到IService层所在程序集中的所有类的对象实例
                Assembly iserAss = Assembly.Load("CommonFrame.IService");
                Assembly serAss = Assembly.Load("CommonFrame.Service");
                //创建serAss中的所有类的instance以此类的实现接口存储
                builder.RegisterAssemblyTypes(iserAss, serAss).AsImplementedInterfaces().PropertiesAutowired();//支持构造方式注入和属性方式注入,不加PropertiesAutowired则只支持构造方式
    
                //告诉autofac框架注册Repository层所在程序集中的所有类的对象实例到IRepository层所在程序集中的所有类的对象实例
                Assembly irepAss = Assembly.Load("CommonFrame.IRepository");
                Assembly repAss = Assembly.Load("CommonFrame.Repository");
                //创建serAss中的所有类的instance以此类的实现接口存储
                builder.RegisterAssemblyTypes(irepAss, repAss).AsImplementedInterfaces().PropertiesAutowired();//支持构造方式注入和属性方式注入,不加PropertiesAutowired则只支持构造方式
                #endregion
    
                #region 另一种注册方式
                ////如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
                //var iServices = Assembly.Load("IocAufoFac.IServices");
                //var services = Assembly.Load("IocAufoFac.Services");
                //var iRepository = Assembly.Load("IocAufoFac.IRepository");
                //var repository = Assembly.Load("IocAufoFac.Repository");
    
                ////根据名称约定(服务层的接口和实现均以Services结尾),实现服务接口和服务实现的依赖
                //builder.RegisterAssemblyTypes(iServices, services)
                //  .Where(t => t.Name.EndsWith("Services"))
                //  .AsImplementedInterfaces();
    
                ////根据名称约定(数据访问层的接口和实现均以Repository结尾),实现数据访问接口和数据访问实现的依赖
                //builder.RegisterAssemblyTypes(iRepository, repository)
                //  .Where(t => t.Name.EndsWith("Repository"))
                //  .AsImplementedInterfaces();
                #endregion
    
                //创建一个Autofac的容器
                var container = builder.Build();
                //将MVC的控制器对象实例 交由autofac来创建
                DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
                #endregion
            }
    View Code

    3、在Global.asax的Application_Start启动方法中添加方法调用

    //autofac注入
    AutoFacConfig.Register();

    4、在使用时通过属性注入得到

    /// <summary>
    /// 属性注入
    /// </summary>
    public IService_Common_Members Iservice_common_members { get; set; }

    二、通过PostSharp实现AOP

    1、使用Nuget引入PostSharp包

    2、新增一个Aop_PostSharp类,代码中存在与记录日志的混合,请将就着看,代码如下

    using log4net;
    using PostSharp.Aspects;
    using PostSharp.Extensibility;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CommonFrame.Web
    {
        [Serializable]
        public class Aop_PostSharp : OnMethodBoundaryAspect
        {
            private static readonly log4net.ILog _logger;
    
            private string _methodName;
            
            private int _hashCode;
    
            static Aop_PostSharp()
            {
                if (!PostSharpEnvironment.IsPostSharpRunning)
                {
                    _logger =
                        log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                }
            }
    
            
            public Aop_PostSharp()
            {
                // Do nothing
            }
    
            public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
            {
                _methodName = "【类名:"+method.DeclaringType.Name + "/方法名:" + method.Name+"";
            }
            
            public override void RuntimeInitialize(MethodBase method)
            {
                _hashCode = this.GetHashCode();
            }
    
            /// <summary>
            /// 方法执行前
            /// </summary>
            /// <param name="args"></param>
            public override void OnEntry(MethodExecutionArgs args)
            {
                //_logger.InfoFormat(">>> Entry [{0}] {1}", _hashCode, _methodName);
            }
    
            /// <summary>
            /// 正常结束时
            /// </summary>
            /// <param name="args"></param>
            public override void OnSuccess(MethodExecutionArgs args)
            {
                //_logger.InfoFormat(">>> Success [{0}] {1}", _hashCode, _methodName);
            }
    
            /// <summary>
            /// 方法执行后
            /// </summary>
            /// <param name="args"></param>
            public override void OnExit(MethodExecutionArgs args)
            {
                //_logger.InfoFormat("<<< Exit [{0}] {1}", _hashCode, _methodName);
            }
    
            /// <summary>
            /// 抛出异常时,记录程序无法处理的异常信息
            /// 已经try catch处理过的,不进入该流程
            /// </summary>
            /// <param name="args"></param>
            public override void OnException(MethodExecutionArgs args)
            {
                string expMsg = string.Format("!!! Exception [{0}] {1} {2}", _hashCode, _methodName, args.Exception.ToString());
                _logger.ErrorFormat(expMsg, args.Exception);
                //重定向到指定的错误页面
                string errorurl = "/Error/Index";
                System.Web.HttpContext.Current.Response.Redirect(errorurl);
            }
        }
    }
    View Code

    3、使用方法,在需要进行aop切入的action上加入上面的类名,具体参照下图

    三、通过log4net实现日志记录

     1、使用Nuget引入log4net包

     2、在Web.config同一目录下添加Log4Net.config,配置如下

    <?xml version="1.0" encoding="UTF-8"?>
    <log4net debug="false">
      <!--Error-->
      <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender">
        <!--是否续写-->
        <param name="AppendToFile" value="true" />
        <!--最小锁定模型以允许多个进程可以写入同一个文件-->
        <param name="LockingModel" value="log4net.Appender.FileAppender.MinimalLock" />
        <param name="StaticLogFileName" value="true" />
        <!--保存路径-->
        <param name="File" value="log\" />
        <param name="DatePattern" value="yyyyMMdd_Error.LOG" />
        <param name="StaticLogFileName" value="false" />
        <param name="RollingStyle" value="Date" />
        <filter type="log4net.Filter.LevelRangeFilter">
          <levelMin value="ERROR" />
          <levelMax value="ERROR" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
          <param name="ConversionPattern" value="时间:%d %n级别:%level %n类名:%c%n文件:%F 第%L行%n错误日志:%m%n-----------------------------------------%n%n" />
        </layout>
      </appender>
      <!--Error-->
    
      <!--Info-->
      <appender name="InfoLog" type="log4net.Appender.RollingFileAppender">
        <!--是否续写-->
        <param name="AppendToFile" value="true" />
        <!--最小锁定模型以允许多个进程可以写入同一个文件-->
        <param name="LockingModel" value="log4net.Appender.FileAppender.MinimalLock" />
        <param name="StaticLogFileName" value="true" />
        <!--保存路径-->
        <param name="File" value="log\" />
        <param name="DatePattern" value="yyyyMMdd_Info.LOG" />
        <param name="StaticLogFileName" value="false" />
        <param name="RollingStyle" value="Date" />
        <filter type="log4net.Filter.LevelRangeFilter">
          <levelMin value="INFO" />
          <levelMax value="INFO" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
          <param name="ConversionPattern" value="时间:%d %n级别:%level %n类名:%c%n文件:%F 第%L行%n日志内容:%m%n-----------------------------------------%n%n" />
        </layout>
      </appender>
    
      <!--按日志容量分割日志文件 10KB一个-->
      <appender name="LogFileAppenderBySize" type="log4net.Appender.RollingFileAppender" >
        <!--是否续写-->
        <param name="AppendToFile" value="true" />
        <!--最小锁定模型以允许多个进程可以写入同一个文件-->
        <param name="LockingModel" value="log4net.Appender.FileAppender.MinimalLock" />
    
        <param name="StaticLogFileName" value="true" />
    
        <!--按照文件的大小进行变换日志文件-->
        <param name="RollingStyle" value="Size" />
        <param name="File" value="log.txt" />
        <!--单个文件最大数量 好像只有在 按Size分割时有效-->
        <param name="MaximumFileSize" value="200KB"/>
        <!--保留的log文件数量 超过此数量后 自动删除之前的   好像只有在 按Size分割时有效-->
        <param name="MaxSizeRollBackups" value="2" />
    
        <param name="StaticLogFileName" value="false" />
        <layout type="log4net.Layout.PatternLayout">
          <param name="ConversionPattern" value="发生时间:%d %n事件级别:%level %n程序文件:%F 第%L行%n日志内容:%m%n-----------------------------------------%n%n" />
        </layout>
      </appender>
    
      <!--记录日志到数据库-->
      <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
        <bufferSize value="1" />
        <!--缓冲大小-->
        <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
        <connectionString value="Data Source=.;Initial Catalog=Common;User ID=sa;Password=123" />
        <commandText value="INSERT INTO Common_Log([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
        <parameter>
          <parameterName value="@log_date" />
          <dbType value="DateTime" />
          <layout type="log4net.Layout.RawTimeStampLayout" />
        </parameter>
        <parameter>
          <parameterName value="@thread" />
          <dbType value="String" />
          <size value="255" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%thread" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@log_level" />
          <dbType value="String" />
          <size value="50" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%level" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@logger" />
          <dbType value="String" />
          <size value="255" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%logger" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@message" />
          <dbType value="String" />
          <size value="4000" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message" />
          </layout>
        </parameter>
        <parameter>
          <parameterName value="@exception" />
          <dbType value="String" />
          <size value="2000" />
          <layout type="log4net.Layout.ExceptionLayout" />
        </parameter>
      </appender>
    
      <root>
        <level value="INFO" />
        <!--启用日志级别为ERROR的日志记录-->
        <appender-ref ref="ErrorLog" />
        <!--启用日志级别为INFO的日志记录-->
        <appender-ref ref="InfoLog" />
        <!--启用按容量分割-->
        <!--<appender-ref ref="LogFileAppenderBySize" />-->
        <!--启用保存到数据库-->
        <appender-ref ref="AdoNetAppender" />
      </root>
    
    </log4net>
    View Code
    USE [Common]
    GO
    
    /****** Object:  Table [dbo].[Common_Log]    Script Date: 06/04/2018 14:29:58 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    SET ANSI_PADDING ON
    GO
    
    CREATE TABLE [dbo].[Common_Log](
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [Date] [datetime] NOT NULL,
        [Thread] [varchar](255) NOT NULL,
        [Level] [varchar](50) NOT NULL,
        [Logger] [varchar](255) NOT NULL,
        [Message] [varchar](4000) NOT NULL,
        [Exception] [varchar](2000) NULL,
     CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    SET ANSI_PADDING OFF
    GO
    LOG表CREATE语句

    3、具体使用方法,本项目都是与AOP进行配合,进行自动记录日志,使日志功能与其他业务功能基本完全解耦

    现已上传将项目源代码上传至GitHub,以便需要的人参考,也望大神指点

    GitHub地址:https://github.com/zhuanshujianghai/NET-MVC4-EF6

  • 相关阅读:
    java 8 stream sql left join =》 jooq & Flink & Scala
    Maven error: lambda expressions are not supported in -source 1.7
    error C2039: 'SetWindowTextA' : is not a member of 'CString'
    循环队列(循环数组)中元素个数的计算
    数据结构之堆
    理解C语言声明的优先级规则
    内联汇编中的asm和__asm__
    程序启动时的堆栈
    局部变量与堆栈
    BCD码干什么用的?
  • 原文地址:https://www.cnblogs.com/jianghaidong/p/9133227.html
Copyright © 2011-2022 走看看