使用Castle DynamicProxy (AOP)
在本文中,我将引导您了解.NET环境中的面向方面编程(AOP)概念,以及如何使用Castle DynamicProxy创建和附加方面。在我们开始之前,让我快速介绍AOP和 IoC。如果您已经熟悉这些概念,则可以完全跳过本节。
什么是AOP?
方面 - 面向对象编程 ( AOP)是一种 编程 范式,旨在通过允许的横切关注分离,以增加模块性。 一个方面是通常分散在方法,类和对象层次结构中的常见功能。看起来像它的行为具有结构,但是找不到使用传统的面向对象技术来表达它的方法。
一个很好的例子就是日志记录,我将在本文中详细讨论。通常,您在代码库中写入信息丰富的日志,但日志记录是您的类或对象模型真的不应该关心的,因为它不代表域对象。
使用AOP方法,我们可以创建这些交叉关注的方面,并使用多种技术将它们集中在域对象上。IL代码编织和截取是广泛使用的方法。在本文中,我将介绍使用Castel Windsor框架动态创建和应用方面的过程。
控制反转(IoC)/依赖注入(DI)容器
IoC容器是一种在需要时自动创建和注入依赖项的框架。DI容器帮助我们以简单和更有效的方式管理应用程序中的依赖关系。
大多数主流DI(依赖注入)容器都内置支持拦截。使用这种方法,您可以在运行时调用和更改域对象的行为来拦截该方法。我们将利用此功能将方面附加到我们的域对象。我的DI框架选择是城堡温莎,其DynamicProxy是应用方面的流行方式之一。
Code Project中有很多很好的文章和不同的博客,可以为您提供有关此(IoC)主题的更多详细信息。关于IoC的详细讨论超出了本文的范围。
拦截使用Castle DynamicProxy
Castle DynamicProxy是一个用于在运行时生成.NET代理的库。它允许您动态地更改和扩展业务对象的行为。这使得您的域模型更加可维护,因为交叉关切纯粹与核心域模型脱钩。如果为任何组件指定拦截器,Castle将自动创建代理。您使用拦截器将代理注入行为。
你可能想知道这整个事情在内部如何工作。每当调用者请求业务对象(具体类)时,IoC容器将在DynamicProxy的帮助下解析并将其包装在包含指定拦截器的代理对象中。容器然后将代理的对象返回给调用者。来电者然后直接与代理人进行交互。代理拦截对业务对象的每个方法调用,并让请求流过拦截器管道。

下图显示了请求如何流入代理。您可以看到请求在实际执行方法之前和之后通过所有拦截器。

在您的项目中设置Castle DynamicProxy的步骤
- 从NuGet下载并安装“Castle.Windsor”软件包。
- 实现IInterceptor接口。这是DynamicProxy将要使用的接口。
- 实施IRegistration界面并注册您的组件。注册拦截器后跟业务组件。指定要与每个业务组件一起使用的拦截器。
- 创建Windsor容器(IWindsorContainer)的静态实例,使用组件注册信息进行初始化。
这几乎是配置Castle DynamicProxy所需要的!
使用代码
让我们从我们的示例应用程序开始。此应用程序包含一个业务对象“火箭”,我们使用控制台应用程序启动。
接口包含一个称为“启动”的单一方法签名。
public interface IRocket
{
void Launch(int delaySeconds);
}
允许通过实现唯一需要的方法“启动”实现接口。
public class Rocket: IRocket
{
public string Name { get; set; }
public string Model { get; set; } public void Launch(int delaySeconds)
{ Console.WriteLine(string.Format("Launching rocket in {0} seconds",delaySeconds));
Thread.Sleep( * delaySeconds);
Console.WriteLine("Congratulations! You have successfully launched the rocket");
}
}
时间来创建我们的第一个拦截器。我们可以通过实现IInterceptor接口来实现。这是DynamicProxy将要使用的接口。
如下所示,我们正在登录方法条目,调用执行实际方法的invocation.Proceed()方法,登录成功执行,登录异常和退出登录。我们不必在其中编写日志记录代码我们的业务模式了!我们只需要将LoggingInterceptor附加到需要记录的组件上。
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var methodName = invocation.Method.Name;
try
{
Console.WriteLine(string.Format("Entered Method:{0}, Arguments: {1}", methodName, string.Join(",", invocation.Arguments)));
invocation.Proceed();
Console.WriteLine(string.Format("Sucessfully executed method:{0}", methodName));
}
catch (Exception e)
{
Console.WriteLine(string.Format("Method:{0}, Exception:{1}", methodName, e.Message));
throw;
}
finally
{
Console.WriteLine(string.Format("Exiting Method:{0}", methodName));
}
}
DynamicProxy公开的IInvocation对象非常有用。它可以访问当前的MethodInfo,Arguments,ReturnValue和许多其他细节,如下所示。
public interface IInvocation
{
object[] Arguments { get; }
Type[] GenericArguments { get; }
object InvocationTarget { get; }
MethodInfo Method { get; }
MethodInfo MethodInvocationTarget { get; }
object Proxy { get; }
object ReturnValue { get; set; }
Type TargetType { get; }
object GetArgumentValue(int index);
MethodInfo GetConcreteMethod();
MethodInfo GetConcreteMethodInvocationTarget();
void Proceed();
void SetArgumentValue(int index, object value);
}
实施IRegistration界面并注册您的组件。注册拦截器后跟业务组件。指定要与每个业务组件一起使用的拦截器。您可能已经注意到,LoggingInterceptor附加到我们唯一的业务组件Rocket
public class ComponentRegistration : IRegistration
{
public void Register(IKernelInternal kernel)
{
kernel.Register(
Component.For<LoggingInterceptor>()
.ImplementedBy<LoggingInterceptor>()); kernel.Register(
Component.For<IRocket>()
.ImplementedBy<Rocket>()
.Interceptors(InterceptorReference.ForType<LoggingInterceptor>()).Anywhere);
}
}
创建Windsor容器(IWindsorContainer)的静态实例,使用组件注册信息进行初始化。
public class DependencyResolver
{
private static IWindsorContainer _container; //Initialize the container
public static void Initialize()
{
_container = new WindsorContainer();
_container.Register(new ComponentRegistration());
} //Resolve types
public static T For<T>()
{
return _container.Resolve<T>();
}
}
用于运行我们的代码的微型控制台应用程序。
internal class Program
{
public static void Main(string[] args)
{
//Initialize the dependency resolver
DependencyResolver.Initialize(); //resolve the type:Rocket
var rocket = DependencyResolver.For<IRocket>(); //method call
try
{
rocket.Launch();
}
catch (Exception ex)
{ }
System.Console.ReadKey(); }
}
让我们看看控制台输出。正如你所期望的,我们的LoggingInterceptor拦截了方法调用和记录的方法条目并自动退出。感谢DynamicProxy!

兴趣点
这是一篇介绍性文章,让初学者和中级开发人员使用Castle Windsor DynamicProxy了解AOP的基本概念。在未来的日子里,我将继续更新本文,并展示如何在Web Api项目中使用Log4net和DynamicProxy实现此解决方案。
使用Castle DynamicProxy (AOP)的更多相关文章
- Castle DynamicProxy基本用法(AOP)
本文介绍AOP编程的基本概念.Castle DynamicProxy(DP)的基本用法,使用第三方扩展实现对异步(async)的支持,结合Autofac演示如何实现AOP编程. AOP 百科中关于AO ...
- 在 CAP 中使用 AOP ( Castle.DynamicProxy )
简介 本篇文章主要介绍如何在 CAP 中集成使用 Castle.DynamicProxy,Castle DynamicProxy 是一个用于在运行时动态生成轻量级.NET代理的库.代理对象允许在不修改 ...
- 基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)
本方案解决了下面3个主要的问题: 1.减少配置,为了避免每次新增service都需要去修改配置文件,包括服务器端跟各个客户端的. 2.能够使用函数重载,泛型函数,以及泛型类. 3.使项目能够快速地在w ...
- 使用MEF与Castle实现AOP
MEF是微软的一个ioc框架,使用非常方便,我们只需要在需要导出的类上标记[Export],在需要使用的地方[import]就可以使用了.现在我们扩展MEF,在其装配生成实例时,使用Castle Dy ...
- C#使用Castle实现AOP面向切面编程
Castle.Core 本质是创建继承原来类的代理类,重写虚方法实现AOP功能.个人觉得比Autofac用着爽 使用方式比较简单,先新建一个控制台项目,然后在Nuget上搜索Castle.Core并安 ...
- 使用 Castle 实现 AOP,以及 Autofac 集成 Castle
Castle 是 2003 年诞生于 Apache Avalon 项目,目的是为了创建一个IOC 框架.发展到现在已经有四个组件: ORM组件:ActiveRecord IOC组件:Windsor 动 ...
- Castle DynamicProxy
Introduction¶ Castle DynamicProxy is a library for generating lightweight .NET proxies on the fly at ...
- Castle.DynamicProxy Part 1: ClassProxy
1.Castle中代理对象的分类 总的来说,代理对象大概可以分为2大类: 1.继承类型的代理对象 一类是继承类型的代理类.即:有一个类A,它的代理类是B.B是继承自A的.调用代理类B中的方法时,可以通 ...
- castle.dynamicProxy学习笔记
目的: 可以将castle.dynamicProxy当成代码生成器,快速的生成自己想的代码.这个库经历了这么多年的测试,应该可以用了:D 概念: IInterceptor:拦截器 当方法(属性的本质是 ...
随机推荐
- 167. 两数之和 II - 输入有序数组
给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的下标值( ...
- 【Zuul】使用学习
[Zuul]使用学习 添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <arti ...
- Ubuntu19.10安装
# 有一说一,UI好看多了 正文开始 # 1.做U盘 # 2.修改BIOS选择U盘引导 底下有提示,F5/F6切换项目 # 3.进入引导盘 这个界面多了比19.10之前的版本多了两个选项, ...
- 你不知道的JavaScript(上)this和对象原型(三)
第四章 混核对象“类” 1.理论 面向对象编程强调的是数据和操作数据的行为本质上是互相关联的.实例化,继承,多态性 javascript中只有对象,并不存在可以被实例化的“类”.一个对象并不会被复制 ...
- 冒泡排序(表格说明)(js)
冒泡排序我自己的理解是(假设从大到小): 比较每一对相邻元素的值,如果前面的元素小于后面的元素那么就将它们交换过来,每次排序的比较次数逐次递减,最后的比较次数为1.总的排序轮数为数组长度减1.为了便于 ...
- 如何减小ABAP业务代码的复杂度
在程序开发的过程中,相同的功能往往有不同的实现方式.对于可以实现同样功能的不同代码,复杂度是用于比较其质量优劣的重要指标. 在本文中,代码复杂度是指代码被理解/修改的难易程度.越容易被理解.修改的代码 ...
- 收到一个神盾局的offer,怎么样?
漫威十一年系列总结性的电影<复联4>正在热映,而衍生出的一部和漫威宇宙关联的美剧<神盾局特工>,今年我也在陆陆续续地看.一开始预期的是一部特工加一些科幻或魔幻元素的剧集,就图看 ...
- 我用 Python 破解了同事的加密压缩包!
作者 | 朱小五 又是一杯奶茶. 事情的经过是这样的: 又是奶茶,行吧快点开工,争取李大伟回来之前搞定 李大伟说是6位数字密码 那么我们可以利用python生成全部的六位数字密码 #生成从 ...
- 周末DHU友谊赛(半日游)感想
DHU的校园挺好的啊,感觉教学楼啊,整体环境啊比咱学校好上一些,和大家一起出来有些春(冬)游的意味,食堂也是十分的宽敞,座位好多! 吐槽shu的食堂座位到饭点明显太少,食堂品类好多,shu的吃多了感觉 ...
- 精通awk系列(10):awk筛选行和处理字段的示例
回到: Linux系列文章 Shell系列文章 Awk系列文章 awk数据筛选示例 筛选行 # 1.根据行号筛选 awk 'NR==2' a.txt # 筛选出第二行 awk 'NR>=2' a ...