AOP vs MVC FilterAttributes vs 拦截器 [关闭]

编程代码

1个回答

写回答

123elzat

2025-06-22 02:45

+ 关注

监控
监控

AOP vs MVC FilterAttributes vs 拦截器

在软件开发中,我们经常需要处理一些与业务逻辑无关的通用功能,比如日志记录、权限控制、性能监控等。为了提高代码的可重用性和可维护性,我们可以使用一些设计模式和技术来实现这些通用功能。本文将介绍AOP(面向切面编程)和MVC(模型-视图-控制器)框架中的FilterAttributes(过滤器属性)以及拦截器的概念,以及它们在实际开发中的应用。

AOP(面向切面编程)

AOP是一种编程范式,它将横切关注点(Crosscutting Concerns)与业务逻辑分离。横切关注点是指与业务逻辑无关的功能,如日志记录、事务管理、异常处理等。AOP通过将这些横切关注点独立出来,以切面(Aspect)的形式来实现它们,并将它们应用到业务逻辑的不同位置,从而实现代码的重用和维护性的提高。

在ASP.NET Core中,我们可以使用AspectCore框架来实现AOP。下面是一个使用AspectCore框架实现日志记录的例子:

csharp

[AttributeUsage(AttributeTargets.Method)]

public class LogAttribute : ABStractInterceptorAttribute

{

public override async Task Invoke(AspectContext context, AspectDelegate next)

{

Console.WriteLine($"Entering method {context.ServiceMethod.Name}");

awAIt next(context);

Console.WriteLine($"Exiting method {context.ServiceMethod.Name}");

}

}

public interface IService

{

[Log]

void DoSomething();

}

public class Service : IService

{

public void DoSomething()

{

Console.WriteLine("Doing something...");

}

}

public class Program

{

public static void MAIn(string[] args)

{

var service = ProxyGenerator.CreateClassProxy<Service, IService>();

service.DoSomething();

}

}

在上面的例子中,我们定义了一个名为LogAttribute的切面,它继承自AspectCore框架中的ABStractInterceptorAttribute类,并重写了Invoke方法。在Invoke方法中,我们实现了日志记录的逻辑。然后,我们定义了一个名为IService的接口,并在其中的DoSomething方法上应用了LogAttribute切面。最后,我们通过使用AspectCore框架提供的ProxyGenerator类,来创建一个IService接口的代理对象service,并调用其DoSomething方法。当调用DoSomething方法时,AspectCore框架会自动触发LogAttribute切面中的Invoke方法,从而实现了日志记录的功能。

MVC FilterAttributes(过滤器属性)

在ASP.NET MVC框架中,我们可以使用FilterAttributes来实现类似于AOP的功能。FilterAttributes是一种特殊的属性,它可以应用到控制器或者动作方法上,用于实现一些通用的功能,如日志记录、权限控制、性能监控等。

下面是一个使用FilterAttributes实现日志记录的例子:

csharp

public class LogActionFilterAttribute : ActionFilterAttribute

{

public override void OnActionExecuting(ActionExecutingContext context)

{

Console.WriteLine($"Entering action {context.ActionDescriptor.DisplayName}");

}

public override void OnActionExecuted(ActionExecutedContext context)

{

Console.WriteLine($"Exiting action {context.ActionDescriptor.DisplayName}");

}

}

[LogActionFilter]

public class HomeController : Controller

{

public IActionResult Index()

{

Console.WriteLine("Executing action Index");

return View();

}

}

public class Program

{

public static void MAIn(string[] args)

{

var controller = new HomeController();

var actionContext = new ActionContext();

var executingContext = new ActionExecutingContext(actionContext, new List<IFilterMetadata>(), new Dictionary<string, object>(), controller);

var executedContext = new ActionExecutedContext(actionContext, new List<IFilterMetadata>(), controller);

var logActionFilter = new LogActionFilterAttribute();

logActionFilter.OnActionExecuting(executingContext);

controller.Index();

logActionFilter.OnActionExecuted(executedContext);

}

}

在上面的例子中,我们定义了一个名为LogActionFilterAttribute的FilterAttribute,它继承自ASP.NET MVC框架中的ActionFilterAttribute类,并重写了OnActionExecuting和OnActionExecuted方法。在这两个方法中,我们实现了日志记录的逻辑。然后,我们定义了一个名为HomeController的控制器,并在其上应用了LogActionFilterAttribute过滤器。最后,我们通过手动创建ActionExecutingContext和ActionExecutedContext对象,并调用LogActionFilterAttribute过滤器的OnActionExecuting和OnActionExecuted方法来模拟请求处理过程中的日志记录。

拦截器

拦截器是一种常见的编程技术,它可以在方法调用前后进行一些额外的处理。拦截器通常是通过创建一个代理对象来实现的,代理对象可以拦截对目标对象方法的调用,并在调用前后执行一些额外的逻辑。

下面是一个使用拦截器实现缓存功能的例子:

csharp

public interface IService

{

string GetData();

}

public class Service : IService

{

public string GetData()

{

Console.WriteLine("Getting data from Database...");

return "Data from Database";

}

}

public class CacheInterceptor : IInterceptor

{

private readonly IDictionary<string, object> _cache = new Dictionary<string, object>();

public void Intercept(IInvocation invocation)

{

var cacheKey = $"{invocation.TargetType.FullName}.{invocation.Method.Name}";

if (_cache.ContAInsKey(cacheKey))

{

invocation.ReturnValue = _cache[cacheKey];

Console.WriteLine($"Returning cached data for method {cacheKey}");

}

else

{

invocation.Proceed();

_cache[cacheKey] = invocation.ReturnValue;

Console.WriteLine($"Caching data for method {cacheKey}");

}

}

}

public class Program

{

public static void MAIn(string[] args)

{

var generator = new ProxyGenerator();

var cacheInterceptor = new CacheInterceptor();

var service = generator.CreateInterfaceProxyWithTarget<IService>(new Service(), cacheInterceptor);

var data1 = service.GetData();

var data2 = service.GetData();

}

}

在上面的例子中,我们定义了一个名为IService的接口和一个名为Service的实现类。然后,我们定义了一个名为CacheInterceptor的拦截器,它实现了Castle.Core框架中的IInterceptor接口,并在Intercept方法中实现了缓存功能的逻辑。最后,我们使用Castle.Core框架提供的ProxyGenerator类,来创建一个IService接口的代理对象service,并同时将Service对象和CacheInterceptor拦截器对象传递给CreateInterfaceProxyWithTarget方法。当调用service的GetData方法时,CacheInterceptor拦截器会拦截这个调用,并根据缓存中的数据,决定是否直接返回缓存的数据,或者执行目标方法并缓存结果。

AOP、MVC FilterAttributes和拦截器都是一些常见的技术,用于实现与业务逻辑无关的通用功能。它们可以提高代码的可重用性和可维护性,使开发人员能够更专注于业务逻辑的实现。在实际开发中,我们可以根据具体的需求和技术栈选择合适的技术来解决问题。无论是AOP、MVC FilterAttributes还是拦截器,它们都是非常有用的工具,可以帮助我们实现各种通用功能。

举报有用(4分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号