Aspect Oriented Programming(AOP)是較為熱門的一個話題。AOP,國內我們都習慣稱之為:面向切面程式設計
下面直接code 乾貨展示:
1:匯入相關的包:AutoFac 預設最新穩定版即可
Autofac.Extensions.DependencyInjection Version="7.1.0"
Autofac.Extras.DynamicProxy Version="6.0.0"
2:AutoFac注入的擴充套件方法
1 using System; 2 using System.Linq; 3 namespace ZRF.CRM.Commoms 4 { 5 using Autofac; 6 using Autofac.Extras.DynamicProxy; 7 using Microsoft.AspNetCore.Mvc; 8 using System.Reflection; 9 using ZRF.CRM.Commoms.Interceptors; 10 using ZRF.CRM.MyAttrobutrs; 11 12 public static class ContainerBuilderExtenTion 13 { 14 public static void DependInjecterIoc(this ContainerBuilder builder) 15 { 16 builder.RegisterType<TransactionScopeAsyncInterCeptor>(); 17 builder.RegisterAssemblyTypes(Assembly.Load("ZRF.CRM.Service")) 18 .AsImplementedInterfaces().PropertiesAutowired().InterceptedBy(typeof(TransactionScopeAsyncInterCeptor)).EnableInterfaceInterceptors().OnRegistered(t => 19 { 20 Console.WriteLine("ZRF.CRM.Service===Register_ok"); 21 }); 22 } 23 } 24 }
3:新增ConfigureContainer(ContainerBuilder builder)方法,並在Startup方法中註冊
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection; 5 using System.Threading.Tasks; 7 using Autofac; 8 using Microsoft.AspNetCore.Builder; 9 using Microsoft.AspNetCore.Hosting; 10 using Microsoft.AspNetCore.Mvc; 11 using Microsoft.AspNetCore.Mvc.Controllers; 12 using Microsoft.Extensions.Configuration; 13 using Microsoft.Extensions.DependencyInjection; 14 using Microsoft.Extensions.DependencyInjection.Extensions; 15 using Microsoft.Extensions.Hosting; 16 using WebApplication1.IOCS; 17 using ZRF.CRM.Commoms; 18 namespace WebApplication1 19 { 20 public class Startup 21 { 22 public Startup(IConfiguration configuration) 23 { 24 Configuration = configuration; 25 } 26 public void ConfigureContainer(ContainerBuilder builder) 27 { 28 builder.DependInjecterIoc(); 29 30 //控制器屬性注入 31 builder.RegisterModule<ControllerModule>(); 32 } 33 public IConfiguration Configuration { get; } 34 35 // This method gets called by the runtime. Use this method to add services to the container. 36 public void ConfigureServices(IServiceCollection services) 37 { 38 services.AddControllersWithViews(); 39 40 //core 3.0級以上 41 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); 42 } 43 44 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 45 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 46 { 47 if (env.IsDevelopment()) 48 { 49 app.UseDeveloperExceptionPage(); 50 } 51 else 52 { 53 app.UseExceptionHandler("/Home/Error"); 54 } 55 app.UseStaticFiles(); 56 57 app.UseRouting(); 58 59 app.UseAuthorization(); 60 61 app.UseEndpoints(endpoints => 62 { 63 endpoints.MapControllerRoute( 64 name: "default", 65 pattern: "{controller=Home}/{action=Index}/{id?}"); 66 }); 67 } 68 } 69 }
4:Controller
1 using Microsoft.AspNetCore.Mvc; 2 using Microsoft.Extensions.Logging; 3 using System; 4 using System.Collections.Generic; 5 using System.Diagnostics; 6 using System.Linq; 7 using System.Threading.Tasks; 8 using WebApplication1.Models; 9 using ZRF.CRM.MyAttrobutrs; 10 using ZRF.CRM.InterFaces; 11 namespace WebApplication1.Controllers 12 { 13 [ControllerCanInjectPropertity] 14 public class HomeController : Controller 15 { 16 private readonly ILogger<HomeController> _logger; 17 18 IDoLog _dolog; 19 ITest002Service _service; 20 public IDoLog _dolog2 { get; set; } 21 22 public HomeController(ILogger<HomeController> logger, IDoLog dolog, ITest002Service service) 23 { 24 _logger = logger; 25 _dolog = dolog; 26 this._service = service; 27 } 28 29 public IActionResult Index() 30 { 31 var boolflag = _dolog2.LogWork("aaaa"); 32 bool flag = _dolog.LogWork("qqai"); 33 var getMsg = _service.Dowork("有aop的方法"); 34 Console.WriteLine("Aop獲取到方法:" + getMsg); 35 //_service.DoWork02("沒有aop的普通方法"); 36 return View(); 37 } 38 39 public IActionResult Privacy() 40 { 41 return View(); 42 } 43 44 [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 45 public IActionResult Error() 46 { 47 return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 48 } 49 } 50 }
5:InterFace
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace ZRF.CRM.InterFaces 6 { 7 8 public interface ITest002Service 9 { 10 string Dowork(string msg); 11 string DoWork02(string msg); 12 } 13 }
6:Service
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 namespace ZRF.CRM.Service 5 { 6 using ZRF.CRM.InterFaces; 7 using ZRF.CRM.MyAttrobutrs; 8 9 public class Test002Service : ITest002Service 10 { 11 [TransactionScopeAsync] 12 public string Dowork(string msg) 13 { 14 15 return $"Test002Service:Dowork {DateTime.Now}-{msg}"; 16 } 17 18 public string DoWork02(string msg) 19 { 20 return $"Test002Service:DoWork02:{DateTime.Now}-{msg}"; 21 } 22 } 23 }
7:自定義特性,將來判斷哪些方法可以aop
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace ZRF.CRM.MyAttrobutrs 6 { 7 [AttributeUsage(AttributeTargets.Method)] 8 public class TransactionScopeAsyncAttribute : Attribute 9 { 10 } 11 12 }
8:自定義類來實現Aop的IInterceptor方法
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace ZRF.CRM.Commoms.Interceptors 6 { 7 using Autofac; 8 using Castle.DynamicProxy; 9 using System.Reflection; 10 using System.Transactions; 11 using ZRF.CRM.MyAttrobutrs; 12 13 public class TransactionScopeAsyncInterCeptor : IInterceptor 14 { 15 public void Intercept(IInvocation invocation) 16 { 17 18 if (HaveAsyncTrascAttribute(invocation)) 19 { 20 TransactionScope scope = null; 21 try 22 { 23 scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); 24 Console.WriteLine("TransactionScopeAsyncFlowOption之前======="); 25 invocation.Proceed(); 26 scope.Complete(); 27 Console.WriteLine("invocation.Proceed()使用者自己的邏輯處理ok======="); 28 Console.WriteLine("TransactionScopeAsyncFlowOption之後======="); 29 } 30 catch (Exception) 31 { 32 Console.WriteLine("TransactionScopeAsyncInterCeptor:發生異常"); 33 if (scope != null) 34 { 35 scope.Dispose(); 36 } 37 } 38 } 39 else { 40 Console.WriteLine("沒有非同步事務發生!"); 41 invocation.Proceed(); 42 return; 43 } 44 } 45 46 private bool HaveAsyncTrascAttribute(IInvocation invocation) 47 { 48 var methodInfo = invocation.MethodInvocationTarget ?? invocation.Method; 49 if (methodInfo.GetCustomAttribute<TransactionScopeAsyncAttribute>() != null) 50 { 51 return true; 52 } 53 else { return false; } 54 } 55 } 56 }
9:來一張測試的截圖
10:最後歡迎留言指教