一、通过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 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
3、具体使用方法,本项目都是与AOP进行配合,进行自动记录日志,使日志功能与其他业务功能基本完全解耦
现已上传将项目源代码上传至GitHub,以便需要的人参考,也望大神指点
GitHub地址:https://github.com/zhuanshujianghai/NET-MVC4-EF6