您的位置:首页 > 编程语言 > ASP

Castle AspectSharp 外部配置方式 测试分析

2006-09-15 17:56 609 查看
F:\开源项目\Dot Net\Castle.NET\Castle-src\Facilities\AspectSharp\AspectSharp.sln

1. ExternalConfigurationTestCase.cs 外部配置测试

using System;

using NUnit.Framework;

using Castle.Model.Configuration;

using Castle.Windsor;

using Castle.Facilities.AspectSharp.Tests.Components;
using Castle.Facilities.AspectSharp.Tests.Interceptors;

/// <summary>
/// Summary description for ExternalConfigurationTestCase.
/// </summary>
[TestFixture]
public class ExternalConfigurationTestCase
{
[Test]
public void ExternalConfigurationUsage()
{
WindsorContainer container = new WindsorContainer( "../aop_castle_config.xml" );

container.AddFacility( "aspectsharp", new AspectSharpFacility() );

// Logger implementation
container.AddComponent( "logger", typeof(ILogger), typeof(MemoryLogger) );

// AopAlliance interceptors
container.AddComponent( "log4netinterceptor", typeof(LoggerTraceInterceptor) );

// Protocol handlers
container.AddComponent( "protocolhandler.miranda",
typeof(IProtocolHandler), typeof(MirandaProtocolHandler) );
container.AddComponent( "protocolhandler.messenger",
typeof(IProtocolHandler), typeof(MessengerProtocolHandler) );

// using


// ILogger logger = (ILogger) container[ typeof(ILogger) ];
// Assert.AreEqual( 0, logger.Contents.Length );

IProtocolHandler handler = (IProtocolHandler)
container[ "protocolhandler.miranda" ];
handler.Handle( "contents" );

handler = (IProtocolHandler) container[ "protocolhandler.messenger" ];
handler.Handle( "contents" );

// Assert.AreEqual( "Entering Handle Leaving Handle Entering Handle Leaving Handle ",
// logger.Contents );
}
}
WindsorContainer 产生的 container 是 Castle 的 IoC 容器,用于动态产生类实例或根据接口动态产生类实例。也可以根据键值从容器中取出实例。

IProtocoHandler handler = (IProtocoHandler) container[ "protocolhandler.miranda" ] 这种调用在失败时会产生异常,

IProtocoHandler handler = container[ "protocolhandler.miranda" ] as IProtocoHandler 这种调用在失败时会使 handler 为 null 。

handler 是两个基于 IProtocolHandler 接口的业务级的例程,Handle(string) 是业务逻辑性质的方法体,没有现实的业务意义,只是用于演示。

2. 象征性的业务性质的 handler 例程 MirandaProtocolHandler.cs

using System;

/// <summary>
/// Summary description for MirandaProtocolHandler.
/// </summary>
public class MirandaProtocolHandler : IProtocolHandler
{
public MirandaProtocolHandler()
{
}

#region IProtocolHandler Members

public void Handle(String contents)
{
Console.WriteLine("MirandaProtocolHandler is handling contents

");

}

#endregion
}
MessengerProtocolHandler 与此一模一样,不同的只是 Handle 方法体的输出信息内容把 Miranda 改为 Messenger。

3. 『logger』,MemoryLogger.cs

这是 1. 中向 IoC container 使用 AddComponent 添加的第一个类

using System;
using System.Text;

/// <summary>
/// Summary description for MemoryLogger.
/// </summary>
public class MemoryLogger : ILogger
{
private StringBuilder _messages = new StringBuilder();

public MemoryLogger()
{
}

#region ILogger Members

public void Trace(String content)
{
Console.WriteLine("Tracing " + content + " ");
}

public void Enter(String name)
{
_messages.Append("Entering " + name + " ");
Console.WriteLine("Entering " + name + " ");
}

public void Leave(String name)
{
_messages.Append("Leaving " + name + " ");
Console.WriteLine("Leaving " + name + " ");
}

public String Contents
{
get { return _messages.ToString(); }
}

#endregion
}
这是测试过程中需要用到的 logger 实例的类声明。实现了 ILogger 接口。

测试用例中只使用了 Enter 和 Leave 两个方法。假设如果成功的话,进入某个方法时会象征性输出日志“Entering....”而结束某方法时会象征性输出日志“Leaving....”

4. 『横切面拦截机』LoggerTraceInterceptor.cs

拦截机是 AOP 的精髓之一,面向方面编程(AOP)意义等同于面向『横切面』编程。在 Castle AspectSharp 的测试用例中展示的都是 AOP 中的 advice 机制,而且都是 around 的,可以自主选择在方法之前还是之后或者两者皆有的地方添加执行横切面性质的额外方法。

using System;

using AopAlliance.Intercept;

using Castle.Facilities.AspectSharp.Tests.Components;

/// <summary>
/// AopAlliance interceptor, however kept within the container
/// </summary>
public class LoggerTraceInterceptor : IMethodInterceptor
{
private ILogger _logger;

public LoggerTraceInterceptor(ILogger logger)
{
_logger = logger;
}

public object Invoke(IMethodInvocation invocation)
{
Console.WriteLine("\nLoggerTraceIntercepter stand by

\n");

_logger.Enter( invocation.Method.Name );

object value = invocation.Proceed();

_logger.Leave( invocation.Method.Name );

return value;
}
}
注意
1)继承了 IMethodInterceptor,告诉 AspectSharp 这是个方法级的拦截机,AspectSharp 还提供了 IConstructoriInterceptor 用于实现针对构造函数的拦截机。
2)这里需要预先注入 logger 实例,构造式注入
3)object value = invocation.Proceed() 指示执行原本的业务方法
4)在 Invoke 方法体内声明了在执行原本的业务方法之前和之后各记录一条日志(Enter 和 Leave),这也就是拦截机的作用。
5)object value = .... 然后必须做 return value ,这是为了实现正常业务逻辑上的对象返回。当然,如果在 invocation.Proceed() 时产生了异常就不会执行 _logger.Leave 和 return value 了。
6)注意 LoggerTraceInterceptor 在代码中是有(且需要)显式声明的,在 ExternalConfigurationTestCase.cs 中,这说明使用拦截机需要『入侵』代码,而下面的 Mixin 混入不需要在代码中声明。

5. 『Mixin(混入)』SecurityMixin.cs

using AspectSharp.Core;

namespace Castle.Facilities.AspectSharp.Tests.Components
{

using System;

/// <summary>
/// Summary description for SecurityMixin.
/// </summary>
public class SecurityMixin : IProxyAware
{
public SecurityMixin()
{
}

public void SetProxy(object proxy)
{
Console.WriteLine("\nSecurityMixin setting proxy

\n");

}
}
}

这个 Mixin 没有出现在 ExternalConfigurationTestCase.cs 代码中,因为它在下面的 aop_castle_config.xml 中声明了,而且在初始化 WindsorContainer IoC 容器时已经载入了这个外部配置文件。

测试输出表明,这个 Mixin 优先于拦截机 Interceptor 执行,且对于每次执行 Handle() 方法仅在最开头时执行一次。

6. 外部配置文件 ..\aop_castle_config.xml

<configuration>

<facilities>
<facility id="aspectsharp">
<![CDATA[
import Castle.Facilities.AspectSharp.Tests.Components in Castle.Facilities.AspectSharp.Tests
import Castle.Facilities.AspectSharp.Tests.Interceptors in Castle.Facilities.AspectSharp.Tests

interceptors [ "key" : LoggerTraceInterceptor ]
mixins [ "key" : SecurityMixin ]

aspect ProtocolHandlerLogger for [ assignableFrom(IProtocolHandler) ]
include "key"

pointcut method(*)
advice("key")
end
end
]]>
</facility>
</facilities>

</configuration>

import .... in .... 完整语法是 import OneNameSpace in OneAssembly 声明了从某个 .NET 程序集中引入命名空间

interceptors [ "key" : LoggerTraceInterceptor ] 声明拦截机,且把 LoggerTraceInterceptor 命名为 "key"
mixins [ "key" : SecurityMixin ] 声明混淆,且把 SecurityMixin 命名为 "key"

aspect ProtocolHandlerLogger 这个只是 aspect 的命名而已,就像类的命名一样

for [ assignableFrom(IProtocolHandler) ] 指示凡实现 IProtocolHandler 接口的类都适用于这个 aspect 过程

如果是 for MirandaProtocolHandler 则是只有 MirandaProtocolHandler 这个类适用于这个 aspect 过程

include "key" 引用之前声明命名为 "key" 的拦截机和混淆

advice("key") 执行名为 "key" 的拦截和混淆,测试输出标明 Mixin 优先于拦截机执行

7. 测试输出

------ Test started: Assembly: Castle.Facilities.AspectSharp.Tests.dll ------

SecurityMixin setting proxy...

LoggerTraceIntercepter stand by ...

Entering Handle
MirandaProtocolHandler is handling contents ...
Leaving Handle

SecurityMixin setting proxy...

LoggerTraceIntercepter stand by ...

Entering Handle
MessengerProtocolHandler is handling contents ...
Leaving Handle

1 passed, 0 failed, 0 skipped, took 1.64 seconds.

Links:

张老三的 Aspect# 文章

http://www.narchitecture.net/Articles/ArticleList.aspx?category=8
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: