使用Autofac完成AOP日志
1、编写AOP类
using Castle.DynamicProxy;
using Newtonsoft.Json;
using StackExchange.Profiling;
using System.Reflection;
namespace Blog.Core.AOP
{
/// <summary>
/// 拦截器BlogLogAOP 继承IInterceptor接口
/// </summary>
public class BlogLogAOP : IInterceptor
{
/// <summary>
/// 实例化IInterceptor唯一方法
/// </summary>
/// <param name="invocation">包含被拦截方法的信息</param>
public void Intercept(IInvocation invocation)
{
string UserName = "Jamin";
//记录被拦截方法信息的日志信息
var dataIntercept = "" +
$"【当前操作用户】:{UserName} \r\n" +
$"【当前执行方法】:{invocation.Method.Name} \r\n" +
$"【携带的参数有】: {string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())} \r\n";
try
{
MiniProfiler.Current.Step($"执行Service方法:{invocation.Method.Name}() -> ");
//在被拦截的方法执行完毕后 继续执行当前方法,注意是被拦截的是异步的
invocation.Proceed();
// 异步获取异常,先执行
if (IsAsyncMethod(invocation.Method))
{
//Wait task execution and modify return value
if (invocation.Method.ReturnType == typeof(Task))
{
invocation.ReturnValue = InternalAsyncHelper.AwaitTaskWithPostActionAndFinally(
(Task)invocation.ReturnValue,
ex =>
{
LogEx(ex, ref dataIntercept);
});
}
else //Task<TResult>
{
invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult(
invocation.Method.ReturnType.GenericTypeArguments[0],
invocation.ReturnValue,
ex =>
{
LogEx(ex, ref dataIntercept);
});
}
}
else
{// 同步1
}
}
catch (Exception ex)// 同步2
{
LogEx(ex, ref dataIntercept);
}
var type = invocation.Method.ReturnType;
if (typeof(Task).IsAssignableFrom(type))
{
var resultProperty = type.GetProperty("Result");
dataIntercept += ($"【执行完成结果】:{JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue))}");
}
else
{
dataIntercept += ($"【执行完成结果】:{invocation.ReturnValue}");
}
// 你的日志记录 比如log4
#region 输出到当前项目日志
var path = Directory.GetCurrentDirectory() + @"\Log";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string fileName = path + $@"\InterceptLog-{DateTime.Now.ToString("yyyyMMddHHmmss")}.log";
StreamWriter sw = File.AppendText(fileName);
sw.WriteLine(dataIntercept);
sw.Close();
#endregion
}
private void LogEx(Exception ex, ref string dataIntercept)
{
if (ex != null)
{
//执行的 service 中,收录异常
MiniProfiler.Current.CustomTiming("Errors:", ex.Message);
//执行的 service 中,捕获异常
dataIntercept += ($"方法执行中出现异常:{ex.Message + ex.InnerException}\r\n");
}
}
public static bool IsAsyncMethod(MethodInfo method)
{
return (
method.ReturnType == typeof(Task) ||
(method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
);
}
}
internal static class InternalAsyncHelper
{
public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Action<Exception> finalAction)
{
Exception exception = null;
try
{
await actualReturnValue;
}
catch (Exception ex)
{
exception = ex;
}
finally
{
finalAction(exception);
}
}
public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<Task> postAction, Action<Exception> finalAction)
{
Exception exception = null;
try
{
var result = await actualReturnValue;
await postAction();
return result;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Action<Exception> finalAction)
{
return typeof(InternalAsyncHelper)
.GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, [actualReturnValue, finalAction]);
}
}
}
2、进行服务注册
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(build =>
{
// AOP
var cacheType = new List<Type>();
build.RegisterType<BlogLogAOP>();
cacheType.Add(typeof(BlogLogAOP));
// 获取 Service.dll 程序集服务,并注册
var assemblysServices = Assembly.LoadFrom(servicesDllFile);
build.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerDependency()
.EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
.InterceptedBy(cacheType.ToArray());//允许将拦截器服务的列表分配给注册。
// 获取 Repository.dll 程序集服务,并注册
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
build.RegisterAssemblyTypes(assemblysRepository)
.AsImplementedInterfaces()
.InstancePerDependency();
});