C# 实现AOP 的几种常见方式
发布日期:2021-05-09 09:35:26 浏览次数:12 分类:博客文章

本文共 25817 字,大约阅读时间需要 86 分钟。

AOP���Aspect Oriented Programming���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

AOP���������������������������������������������������������������������������������������������������������������������������������������������������

class RealA    {        public virtual string Pro { get; set; }        public virtual void ShowHello(string name)        {            Console.WriteLine($"Hello!{name},Welcome!");        }    }//���������            var a = new RealA();            a.Pro = "������";            a.ShowHello("������������");

������������������������������NEW������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RealA������������������ProxyRealA���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������C#���������������������������������������������������������������virtual���

���������������

class ProxyRealA : RealA    {        public override string Pro        {            get            {                return base.Pro;            }            set            {                ShowLog("������Pro���������������������");                base.Pro = value;                ShowLog($"������Pro���������������������:{value}");            }        }        public override void ShowHello(string name)        {            try            {                ShowLog("ShowHello���������������������");                base.ShowHello(name);                ShowLog("ShowHello���������������������");            }            catch(Exception ex)            {                ShowLog($"ShowHello���������������������������{ex.Message}");            }        }        private void ShowLog(string log)        {            Console.WriteLine($"{DateTime.Now.ToString()}-{log}");        }    }//���������            var aa = new ProxyRealA();            aa.Pro = "������2";            aa.ShowHello("zuowenjun.cn");

������������������������������������ProxyRealA���������RealA���������������������ProxyRealA������RealA������ProxyRealA���������������������������������������������ProxyRealA������������������������������������������������������������������������������������������������RealA������������������������ProxyRealA������������������������������������������������������������������������������������������������������������������������������������ProxyRealA������������������������������������������ProxyRealA������������������������������������������������������������������������������

 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RealA������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������AOP���������������������������������������

������������������������������������������������������������������AOP������������������������������������������������������������������������������������������RealA���������������������������������������������������������������������������������������������������

PostSharp:PostSharp���Aspect���������Attribute���������,���������������������������������OnMethodBoundaryAspect���������������������������������������������������OnEntry���OnExit������������������������������������AOP���������������������������������AOP������������������������������PostSharp���������������������������������������������������������EMIT������������������������������������PostSharp������������������������������������������������������������������������������������������������������������

������������EMIT���������������������Emit������������������������������������Castle.DynamicProxy���AOP������������������������������������������������������������������������������������������������������������������������������������������������������

using Castle.Core.Interceptor;using Castle.DynamicProxy;using NLog;using NLog.Config;using NLog.Win32.Targets;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ConsoleApp{    class Program    {        static void Main(string[] args)        {            ProxyGenerator generator = new ProxyGenerator();            var test = generator.CreateClassProxy
(new TestInterceptor()); Console.WriteLine($"GetResult:{test.GetResult(Console.ReadLine())}"); test.GetResult2("test"); Console.ReadKey(); } } public class TestInterceptor : StandardInterceptor { private static NLog.Logger logger; protected override void PreProceed(IInvocation invocation) { Console.WriteLine(invocation.Method.Name + "���������,���������" + string.Join(",", invocation.Arguments)); } protected override void PerformProceed(IInvocation invocation) { Console.WriteLine(invocation.Method.Name + "���������"); try { base.PerformProceed(invocation); } catch (Exception ex) { HandleException(ex); } } protected override void PostProceed(IInvocation invocation) { Console.WriteLine(invocation.Method.Name + "������������������������" + invocation.ReturnValue); } private void HandleException(Exception ex) { if (logger == null) { LoggingConfiguration config = new LoggingConfiguration(); ColoredConsoleTarget consoleTarget = new ColoredConsoleTarget(); consoleTarget.Layout = "${date:format=HH\\:MM\\:ss} ${logger} ${message}"; config.AddTarget("console", consoleTarget); LoggingRule rule1 = new LoggingRule("*", LogLevel.Debug, consoleTarget); config.LoggingRules.Add(rule1); LogManager.Configuration = config; logger = LogManager.GetCurrentClassLogger(); //new NLog.LogFactory().GetCurrentClassLogger(); } logger.ErrorException("error",ex); } } public class TestA { public virtual string GetResult(string msg) { string str = $"{DateTime.Now.ToString("yyyy-mm-dd HH:mm:ss")}---{msg}"; return str; } public virtual string GetResult2(string msg) { throw new Exception("throw Exception!"); } }}

������������������������������������������ProxyGenerator���������������������������������������������������������������������������������������������������StandardInterceptor���TestInterceptor���������TestInterceptor���������������������������������������������generator.CreateClassProxy<TestA>(new TestInterceptor())������������������������������TestA���������������������������������������������������������������������������������������������������������������������������������������������Test������TestA������������������������������������������������������������������������������������������������������������������������������������������virtual������������������������������������������������������������

���������������������������������

 ������������������������+������Remoting������������������������������������������������������������������������������������������������������������������������

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.Remoting.Activation;using System.Runtime.Remoting.Messaging;using System.Runtime.Remoting.Proxies;using System.Text;using System.Threading.Tasks;namespace ConsoleApp{    class Program    {        static void Main(string[] args)        {            var A = new AopClass();            A.Hello();            var aop = new AopClassSub("������������");            aop.Pro = "test";            aop.Output("hlf");            aop.ShowMsg();            Console.ReadKey();        }    }    [AopAttribute]    public class AopClass : ContextBoundObject    {        public string Hello()        {            return "welcome";        }    }    public class AopClassSub : AopClass    {        public string Pro = null;        private string Msg = null;        public AopClassSub(string msg)        {            Msg = msg;        }        public void Output(string name)        {            Console.WriteLine(name + ",���������-->P:" + Pro);        }        public void ShowMsg()        {            Console.WriteLine($"������������������Msg������������������{Msg}");        }    }    public class AopAttribute : ProxyAttribute    {        public override MarshalByRefObject CreateInstance(Type serverType)        {            AopProxy realProxy = new AopProxy(serverType);            return realProxy.GetTransparentProxy() as MarshalByRefObject;        }    }    public class AopProxy : RealProxy    {        public AopProxy(Type serverType)            : base(serverType) { }        public override IMessage Invoke(IMessage msg)        {            if (msg is IConstructionCallMessage)            {                IConstructionCallMessage constructCallMsg = msg as IConstructionCallMessage;                IConstructionReturnMessage constructionReturnMessage = this.InitializeServerObject((IConstructionCallMessage)msg);                RealProxy.SetStubData(this, constructionReturnMessage.ReturnValue);                Console.WriteLine("Call constructor");                return constructionReturnMessage;            }            else            {                IMethodCallMessage callMsg = msg as IMethodCallMessage;                IMessage message;                try                {                    Console.WriteLine(callMsg.MethodName + "������������������");                    object[] args = callMsg.Args;                    object o = callMsg.MethodBase.Invoke(GetUnwrappedServer(), args);                    Console.WriteLine(callMsg.MethodName + "������������������");                    message = new ReturnMessage(o, args, args.Length, callMsg.LogicalCallContext, callMsg);                }                catch (Exception e)                {                    message = new ReturnMessage(e, callMsg);                }                Console.WriteLine(message.Properties["__Return"]);                return message;            }        }    }}

���������������������������������

1.������������������������������AopClass���������������ContextBoundObject���������ContextBoundObject���������������������MarshalByRefObject���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

2.���������������ProxyAttribute������������������������AopAttribute���������������������������������������������������������CreateInstance������������CreateInstance���������������������������������������������������������������realProxy.GetTransparentProxy() ������������������������������������������AopProxy���������������������������������������������������

3.���������������AopProxy������������������������������������RealProxy������������������������������������Invoke���������������������������������������������������������������������������������������������������������������������������������������������������IMessage���������������������������������������������������

4.���������������������Aop���������������������AopAttribute������������������������������������������������1���������������������ContextBoundObject������������������������������������������������������������������������AopAttribute���������������������������������������������������������������������������������

���������������������������������

������������������������������������������RealProxy���������AOP���������������������

 ������������������+ ������������������������������������������������������������AOP������������������������������MVC���WEB API��������������������� ������������������MVC������������������������������MVC������������AOP���������������������������������������������������������������������������������������������������������������MVC���������������������������������������������Controller������Action���������������������������������������������������

 ���������������������

A.������������Controller���������������������������������

1.���������������������������������Controller������������ 

2.������Controller������������������1������������������Controller������������FindControllerType

3.���������������Controller���������Action���������������������������������FindAction

4.������Controller������������������

5.������Action���������������������������������������������������������������������������������������������������

6.������Controller������OnActionExecuting���������������������������������������������������������������ActionExecutingFilter

7.������Action������������������������

8.������Controller������OnActionExecuted���������������������������������������������������������������ActionExecutedFilter

9.������try catch���catch���������Controller������OnActionError���������������������������������������������������������ActionErrorFilter

10.���������������������

B.���������������������������������������

1.������������������������������������������AddExecRouteTemplate���������������������controller���action���������������������������������������������������������������������������routeTemplates��� 

2.���������������������������������������Controller������Action������������������ Run���������������������������������������������������������������������������������������������������������������������������OK���������������������Controller���Action���������������������������������������������Process���������������A���������������������������������������

���������������������MVC���������������������Action���������������������������������������ModelBinding���������������������������������������������������������������������AOP���������������������������������������������������������������������������������������������MVC���������ASP.NET MVC��������������� Console MVC,���������Winform MVC������

������������������������������������������������������������������������������������������������������

public abstract class Controller    {        public virtual void OnActionExecuting(MethodInfo action)        {        }        public virtual void OnActionExecuted(MethodInfo action)        {        }        public virtual void OnActionError(MethodInfo action, Exception ex)        {        }    }    public abstract class FilterAttribute : Attribute    {        public abstract string FilterType { get; }        public abstract void Execute(Controller ctrller, object extData);    }    public class ActionExecutingFilter : FilterAttribute    {        public override string FilterType => "BEFORE";        public override void Execute(Controller ctrller, object extData)        {            Console.WriteLine($"���������{ctrller.GetType().Name}.ActionExecutingFilter���������������������������-{DateTime.Now.ToString()}");        }    }    public class ActionExecutedFilter : FilterAttribute    {        public override string FilterType => "AFTER";        public override void Execute(Controller ctrller, object extData)        {            Console.WriteLine($"���������{ctrller.GetType().Name}.ActionExecutedFilter���������������������������-{DateTime.Now.ToString()}");        }    }    public class ActionErrorFilter : FilterAttribute    {        public override string FilterType => "EXCEPTION";        public override void Execute(Controller ctrller, object extData)        {            Console.WriteLine($"���������{ctrller.GetType().Name}.ActionErrorFilter���������������������������-{DateTime.Now.ToString()}-Error Msg:{(extData as Exception).Message}");        }    }    public class AppContext    {        private static readonly Type ControllerType = typeof(Controller);        private static readonly Dictionary
matchedControllerTypes = new Dictionary
(); private static readonly Dictionary
matchedControllerActions = new Dictionary
(); private Dictionary
routeTemplates = new Dictionary
(); public void AddExecRouteTemplate(string execRouteTemplate) { if (!Regex.IsMatch(execRouteTemplate, "{controller}", RegexOptions.IgnoreCase)) { throw new ArgumentException("������������������������������������{controller}"); } if (!Regex.IsMatch(execRouteTemplate, "{action}", RegexOptions.IgnoreCase)) { throw new ArgumentException("������������������������������������{action}"); } string[] keys = Regex.Matches(execRouteTemplate, @"(?<={)\w+(?=})", RegexOptions.IgnoreCase).Cast
().Select(c => c.Value.ToLower()).ToArray(); routeTemplates.Add(execRouteTemplate,keys); } public object Run(string execRoute) { //{controller}/{action}/{id} string ctrller = null; string actionName = null; ArrayList args = null; Type controllerType = null; bool findResult = false; foreach (var r in routeTemplates) { string[] keys = r.Value; string execRoutePattern = Regex.Replace(r.Key, @"{(?
\w+)}", (m) => string.Format(@"(?<{0}>.[^/\\]+)", m.Groups["key"].Value.ToLower()), RegexOptions.IgnoreCase); args = new ArrayList(); if (Regex.IsMatch(execRoute, execRoutePattern)) { var match = Regex.Match(execRoute, execRoutePattern); for (int i = 0; i < keys.Length; i++) { if ("controller".Equals(keys[i], StringComparison.OrdinalIgnoreCase)) { ctrller = match.Groups["controller"].Value; } else if ("action".Equals(keys[i], StringComparison.OrdinalIgnoreCase)) { actionName = match.Groups["action"].Value; } else { args.Add(match.Groups[keys[i]].Value); } } if ((controllerType = FindControllerType(ctrller)) != null && FindAction(controllerType, actionName, args.ToArray()) != null) { findResult = true; break; } } } if (findResult) { return Process(ctrller, actionName, args.ToArray()); } else { throw new Exception($"������������������������������������������������������������������������������������������{execRoute}"); } } public object Process(string ctrller, string actionName, params object[] args) { Type matchedControllerType = FindControllerType(ctrller); if (matchedControllerType == null) { throw new ArgumentException($"������������������{ctrller}���Controller������"); } object execResult = null; if (matchedControllerType != null) { var matchedController = (Controller)Activator.CreateInstance(matchedControllerType); MethodInfo action = FindAction(matchedControllerType, actionName, args); if (action == null) { throw new ArgumentException($"���{matchedControllerType.FullName}���������������������������{actionName}������������������{args.Count()}������������������"); } var filters = action.GetCustomAttributes
(true); List
execBeforeFilters = new List
(); List
execAfterFilters = new List
(); List
exceptionFilters = new List
(); if (filters != null && filters.Count() > 0) { execBeforeFilters = filters.Where(f => f.FilterType == "BEFORE").ToList(); execAfterFilters = filters.Where(f => f.FilterType == "AFTER").ToList(); exceptionFilters = filters.Where(f => f.FilterType == "EXCEPTION").ToList(); } try { matchedController.OnActionExecuting(action); if (execBeforeFilters != null && execBeforeFilters.Count > 0) { execBeforeFilters.ForEach(f => f.Execute(matchedController, null)); } var mParams = action.GetParameters(); object[] newArgs = new object[args.Length]; for (int i = 0; i < mParams.Length; i++) { newArgs[i] = Convert.ChangeType(args[i], mParams[i].ParameterType); } execResult = action.Invoke(matchedController, newArgs); matchedController.OnActionExecuted(action); if (execBeforeFilters != null && execBeforeFilters.Count > 0) { execAfterFilters.ForEach(f => f.Execute(matchedController, null)); } } catch (Exception ex) { matchedController.OnActionError(action, ex); if (exceptionFilters != null && exceptionFilters.Count > 0) { exceptionFilters.ForEach(f => f.Execute(matchedController, ex)); } } } return execResult; } private Type FindControllerType(string ctrller) { Type matchedControllerType = null; if (!matchedControllerTypes.ContainsKey(ctrller)) { var assy = Assembly.GetAssembly(typeof(Controller)); foreach (var m in assy.GetModules(false)) { foreach (var t in m.GetTypes()) { if (ControllerType.IsAssignableFrom(t) && !t.IsAbstract) { if (t.Name.Equals(ctrller, StringComparison.OrdinalIgnoreCase) || t.Name.Equals($"{ctrller}Controller", StringComparison.OrdinalIgnoreCase)) { matchedControllerType = t; matchedControllerTypes[ctrller] = matchedControllerType; break; } } } } } else { matchedControllerType = matchedControllerTypes[ctrller]; } return matchedControllerType; } private MethodInfo FindAction(Type matchedControllerType, string actionName, object[] args) { string ctrlerWithActionKey = $"{matchedControllerType.FullName}.{actionName}"; MethodInfo action = null; if (!matchedControllerActions.ContainsKey(ctrlerWithActionKey)) { if (args == null) args = new object[0]; foreach (var m in matchedControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public)) { if (m.Name.Equals(actionName, StringComparison.OrdinalIgnoreCase) && m.GetParameters().Length == args.Length) { action = m; matchedControllerActions[ctrlerWithActionKey] = action; break; } } } else { action = matchedControllerActions[ctrlerWithActionKey]; } return action; } }

������������������������������������Controller���������������TestController������������������������������������������������������������������������������������������������������������

public class TestController : Controller    {        public override void OnActionExecuting(MethodInfo action)        {            Console.WriteLine($"{action.Name}������������OnActionExecuting---{DateTime.Now.ToString()}");        }        public override void OnActionExecuted(MethodInfo action)        {            Console.WriteLine($"{action.Name}������������OnActionExecuted--{DateTime.Now.ToString()}");        }        public override void OnActionError(MethodInfo action, Exception ex)        {            Console.WriteLine($"{action.Name}���������OnActionError--{DateTime.Now.ToString()}:{ex.Message}");        }        [ActionExecutingFilter]        [ActionExecutedFilter]        public string HelloWorld(string name)        {            return ($"Hello World!->{name}");        }        [ActionExecutingFilter]        [ActionExecutedFilter]        [ActionErrorFilter]        public string TestError(string name)        {            throw new Exception("������������������������������������");        }        [ActionExecutingFilter]        [ActionExecutedFilter]        public int Add(int a, int b)        {            return a + b;        }    }

������������������������������������������������������������

class MVCProgram    {        static void Main(string[] args)        {            try            {                var appContext = new AppContext();                object rs = appContext.Process("Test", "HelloWorld", "������������");                Console.WriteLine($"Process���������������1���{rs}");                Console.WriteLine("=".PadRight(50, '='));                appContext.AddExecRouteTemplate("{controller}/{action}/{name}");                appContext.AddExecRouteTemplate("{action}/{controller}/{name}");                object result1 = appContext.Run("HelloWorld/Test/������������-zuowenjun.cn");                Console.WriteLine($"���������������1���{result1}");                Console.WriteLine("=".PadRight(50, '='));                object result2 = appContext.Run("Test/HelloWorld/������������-zuowenjun.cn");                Console.WriteLine($"���������������2���{result2}");                Console.WriteLine("=".PadRight(50, '='));                appContext.AddExecRouteTemplate("{action}/{controller}/{a}/{b}");                object result3 = appContext.Run("Add/Test/500/20");                Console.WriteLine($"���������������3���{result3}");                object result4 = appContext.Run("Test/TestError/������������-zuowenjun.cn");                Console.WriteLine($"���������������4���{result4}");            }            catch (Exception ex)            {                Console.ForegroundColor = ConsoleColor.Red;                Console.WriteLine($"���������������{ex.Message}");                Console.ResetColor();            }            Console.ReadKey();        }    }

������������������ASP.NET MVC���������������������ASP.NET MVC���������URL���������������������������AppContext.Run ������������URL ���Process���������������������Controller���Action���������������������

���������������������������������������������������������������������������������������������������������������������������������������������������������������������������

 MVC���������������������������

上一篇:基于ASP.NET WEB API实现分布式数据访问中间层(提供对数据库的CRUD)
下一篇:SignalR的另类实现技巧

发表评论

最新留言

表示我来过!
[***.240.166.169]2025年04月14日 21时29分27秒