一、通过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 ???????}
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); ???????} ???}}
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_In\fo.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>
USE [Common]GO/****** Object: ?Table [dbo].[Common_Log] ???Script Date: 06/04/2018 14:29:58 ******/SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE 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]GOSET ANSI_PADDING OFFGO
3、具体使用方法,本项目都是与AOP进行配合,进行自动记录日志,使日志功能与其他业务功能基本完全解耦
现已上传将项目源代码上传至GitHub,以便需要的人参考,也望大神指点
GitHub地址:https://github.com/zhuanshujianghai/NET-MVC4-EF6
【进击.NET高级程序员之路】【二】
原文地址:https://www.cnblogs.com/jianghaidong/p/9133227.html