欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET Core 3.0 使用AspectCore-Framework实现AOP

程序员文章站 2023-09-07 00:00:05
AspectCore是适用于Asp.Net Core 平台的轻量级Aop(Aspect oriented programming)解决方案,它更好的遵循Asp.Net Core的模块化开发理念,使用AspectCore可以更容易构建低耦合、易扩展的Web应用程序。 在使用过程中,由于相关文档、博客还 ......

aspectcore是适用于asp.net core 平台的轻量级aop(aspect-oriented programming)解决方案,它更好的遵循asp.net core的模块化开发理念,使用aspectcore可以更容易构建低耦合、易扩展的web应用程序。

在使用过程中,由于相关文档、博客还未更新到.net core 3.0,本文操作参考了使用.net core 3.0的easycaching,并对其中公用的方法进行封装简化。

安装aspectcore

此处配合微软自家的di实现,安装nuget包aspectcore.extensions.dependencyinjection,其中包含aspectcore.core和microsoft.extensions.dependencyinjection两个依赖。

install-package aspectcore.extensions.dependencyinjection -version 1.3.0

拦截器

  • 特性拦截器
    新建一个特性拦截器testinterceptorattribute,继承abstractinterceptorattribute,并重写invoke方法,在方法中实现拦截相关业务。
public class testinterceptorattribute : abstractinterceptorattribute
{
    public override task invoke(aspectcontext context, aspectdelegate next)
    {
        return context.invoke(next);
    }
}
  • 全局拦截器
    新建一个全局拦截器testinterceptor,继承abstractinterceptor,并重写invoke方法,在方法中实现拦截相关业务。
public class testinterceptor : abstractinterceptor
{
    public override task invoke(aspectcontext context, aspectdelegate next)
    {
        return context.invoke(next);
    }
}

注册服务

以下注册方式仅适用于asp.net core 3.0(目前只到3.0),已知在2.2版本中,需要在configureservices方法中返回iserviceprovider,并且program.cs中也不再需要替换serviceproviderfactory。
1.创建aspectcoreectensions.cs扩展iservicecollection

public static class aspectcoreextensions
{
    public static void configaspectcore(this iservicecollection services)
    {
        services.configuredynamicproxy(config =>
        {
            //testinterceptor拦截器类
            //拦截代理所有service结尾的类
            config.interceptors.addtyped<testinterceptor>(predicates.forservice("*service"));
        });
        services.buildaspectinjectorprovider();
    }
}

2.在startup.cs中注册服务

public void configureservices(iservicecollection services)
{   
    services.configaspectcore();
}

3.在program.cs中替换serviceproviderfactory

public static ihostbuilder createhostbuilder(string[] args) =>
    host.createdefaultbuilder(args)
    .configurewebhostdefaults(webbuilder =>
    {
        webbuilder.usestartup<startup>();
    }).useserviceproviderfactory(new aspectcoreserviceproviderfactory());

被拦截方法编写

  • 代理接口:在接口上标注attribute
public interface itestservice
{
    [testinterceptor]
    void test();
}
  • 代理类(方法):在方法上标注attribute,并且标注virtual
public class testservice
{
    [testinterceptor]
    public virtual void test()
    {
        //业务代码
    }
}

拦截器业务编写

  • 执行被拦截方法
private async task<object> runandgetreturn()
{
    await context.invoke(next);
    return context.isasync()
        ? await context.unwrapasyncreturnvalue()
        : context.returnvalue;
}
  • 拦截器中的依赖注入
[fromcontainer]
private redisclient redisclient { get; set; }
  • 获取被拦截方法的attribute
private static readonly concurrentdictionary<methodinfo, object[]>
                    methodattributes = new concurrentdictionary<methodinfo, object[]>();

public static t getattribute<t>(this aspectcontext context) where t : attribute
{
    methodinfo method = context.servicemethod;
    var attributes = methodattributes.getoradd(method, method.getcustomattributes(true));
    var attribute = attributes.firstordefault(x => typeof(t).isassignablefrom(x.gettype()));
    if (attribute is t)
    {
        return (t)attribute;
    }
    return null;
}
  • 获取被拦截方法返回值类型
public static type getreturntype(this aspectcontext context)
{
    return context.isasync()
        ? context.servicemethod.returntype.getgenericarguments()first()
        : context.servicemethod.returntype;
}
  • 处理拦截器返回结果
private static readonly concurrentdictionary<type, methodinfo>
                   typeoftaskresultmethod = new concurrentdictionary<type, methodinfo>();
public object resultfactory(this aspectcontext context,object result)
{
    var returntype = context.getreturntype();

    //异步方法返回task<t>类型结果
    if (context.isasync())
    {
        return typeoftaskresultmethod
                .getoradd(returntype, t => typeof(task)
                .getmethods()
                .first(p => p.name == "fromresult" && p.containsgenericparameters)
                .makegenericmethod(returntype))
                .invoke(null, new object[] { result });
    }
    else
    {
        return result;
    }
}

相关链接