Asp.netCore 3.1控制器屬性注入and非同步事務Aop by AutoFac

jason發表於2021-01-30

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:最後歡迎留言指教

 

相關文章