完全通过配置实现AOP的资料太少了,今天忙了好几个小时终于走通了,分享一下。
模拟业务是:登陆,记录登陆日志。
// 业务接口
public interface IStudentManage
{
bool Login(string userId, string userName);
}
public class StudentManage:IStudentManage
{
public StudentManage() { }
public bool Login(string userId, string userName)
{
return userId == "123" && userName == "123";
}
}
/// <summary>
/// 登陆日志
/// </summary>
public class UserLogCallHandler : ICallHandler
{
/// <summary>
/// 构造函数,此构造函数是用于Attribute调用
/// </summary>
/// <param name="message"> 消息 </param>
/// <param name="parameterName"> 参数名 </param>
public UserLogCallHandler(string message, string parameterName)
{
this.Message = message;
this.ParameterName = parameterName;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
//检查参数是否存在
if (input == null) throw new ArgumentNullException("input");
if (getNext == null) throw new ArgumentNullException("getNext");
//开始拦截,此处可以根据需求编写具体业务逻辑代码
//调用具体方法
var result = getNext()(input, getNext);
// 记录登陆日志
}
public string Message { get; set; }
public string ParameterName { get; set; }
private int order = 0;
public int Order
{
get
{
return order;
}
set
{
order = value;
}
}
}
最关键的XML配置
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="UnityAOPConfig"/>
<namespace name="UnityAOPConfig"/>
<!--新增配置节扩展,用于下面的<interception>配置节-->
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,
Microsoft.Practices.Unity.Interception.Configuration" />
<container name="LoginContainer">
<!--为容器增加Interception扩展,如不增加下面interception配置会报错-->
<extension type="Interception"/>
<interception>
<!--增加一个名为UserLog的拦截策略,用于记录日志-->
<policy name="UserLog">
<!--新增MemberNameMatchingRule匹配规则,同时需要同过配置初始化匹配规则构造函数
具体可查看Unity.InterceptionExtension.PolicyInjection.MatchRule下具体类-->
<matchingRule name="rule1" type="MemberNameMatchingRule">
<lifetime type="singleton"/>
<constructor>
<param name="nameToMatch" value="Login"/>
</constructor>
</matchingRule>
<!--增加调用处理程序,这边指定的是我自定义的UserLogCallHandler-->
<!--同样也需要初始化构造函数-->
<callHandler name="handler1"
type="UserLogCallHandler">
<lifetime type="singleton"/>
<constructor>
<param name="message" type="System.String" value="登录成功!">
</param>
<param name="parameterName" type="System.String" value=" ">
</param>
</constructor>
</callHandler>
</policy>
</interception>
<!--注册对象关系,需要注意的是需要为这个注册增加TransparentProxyInterceptor的拦截器-->
<register type="IStudentManage" mapTo="StudentManage">
<interceptor type="TransparentProxyInterceptor" />
<interceptionBehavior type="PolicyInjectionBehavior" />
</register>
</container>
</unity>
</configuration>
前台调用代码
public static IUnityContainer GetIUnityContainer(string nodeName)
{
//根据文件名获取指定config文件
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = "Web.config" };
//从config文件中读取配置信息
Configuration configuration =
ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var unitySection = (UnityConfigurationSection)configuration.GetSection("unity");
var container = new UnityContainer().LoadConfiguration(unitySection, nodeName);
return container;
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
IUnityContainer container = new UnityContainer().LoadConfiguration("LoginContainer");
IStudentManage studentBll = container.Resolve<IStudentManage>();
if (studentBll.Login(txtUid.Text.Trim(), txtPwd.Text.Trim()))
{
if (string.IsNullOrEmpty(Request.QueryString["returnUrl"]) == false)
{
Response.Redirect(Request.QueryString["returnUrl"]);
}
else
{
Response.Redirect("~/Default.aspx");
}
}
else
{
ltMsg.Text = "用户名或密码不正确,请重试!";
}
}
}