完全通過配置實現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 = "用戶名或密碼不正確,請重試!"; } } }