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

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/jianghaidong/p/9133227.html
Copyright © 2011-2022 走看看