欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

Asp .Net Core 系列:基于 Castle DynamicProxy + Autofac 實(shí)踐 AOP 以及實(shí)現(xiàn)事務(wù)、用戶填充功能

freeflydom
2024年9月13日 9:24 本文熱度 866

什么是 AOP ?

AOP(Aspect-Oriented Programming,面向切面編程)是一種編程范式,旨在通過將橫切關(guān)注點(diǎn)(cross-cutting concerns)從主要業(yè)務(wù)邏輯中分離出來,以提高代碼的模塊化性、可維護(hù)性和復(fù)用性。

在傳統(tǒng)的面向?qū)ο缶幊讨?,我們通常通過類和對象來組織和實(shí)現(xiàn)功能。然而,某些功能,如日志記錄、事務(wù)管理、安全性檢查等,可能會跨越多個對象和模塊,這種跨越稱為橫切關(guān)注點(diǎn)。AOP 的核心思想是將這些橫切關(guān)注點(diǎn)從業(yè)務(wù)邏輯中分離出來,通過特定的機(jī)制將它們應(yīng)用到代碼中,而不是通過直接修改業(yè)務(wù)邏輯來實(shí)現(xiàn)。

.Net Core 中 有哪些 AOP 框架?

PostSharp(收費(fèi))

PostSharp是一個功能強(qiáng)大的AOP框架,它通過編譯器插件的形式集成到Visual Studio中。PostSharp支持編譯時AOP(通過C#特性應(yīng)用切面),并提供了豐富的切面類型,包括方法攔截、屬性訪問攔截、異常處理等。它還提供了商業(yè)支持和豐富的文檔。

Castle DynamicProxy

Castle DynamicProxy是Castle項(xiàng)目的一部分,它允許開發(fā)者在運(yùn)行時動態(tài)創(chuàng)建代理類,這些代理類可以攔截對目標(biāo)對象的調(diào)用,并在調(diào)用前后執(zhí)行自定義邏輯。雖然它本身不是一個完整的AOP框架,但它經(jīng)常被用作構(gòu)建AOP解決方案的基礎(chǔ)。

AspectCore Framework

AspectCore 是一個開源的 AOP 框架,專為 .NET Core 設(shè)計(jì)。它提供了基于動態(tài)代理的運(yùn)行時切面和方法攔截機(jī)制,支持常見的切面編程需求,如日志、緩存、事務(wù)等。

基于 Castle DynamicProxy 實(shí)現(xiàn) AOP

1. 安裝Castle.Core NuGet包

Install-Package Castle.Core


2. 定義接口和類

假設(shè)你有一個接口和一個實(shí)現(xiàn)了該接口的類,你想要攔截這個類的方法調(diào)用。

public interface IMyService  

{  

    void PerformAction();  

}   

public class MyService : IMyService  

{  

    public void PerformAction()  

    {  

        Console.WriteLine("Action performed.");  

    }  

}

3. 創(chuàng)建攔截器

接下來,你需要創(chuàng)建一個攔截器類,該類將實(shí)現(xiàn)IInterceptor接口。在這個接口的實(shí)現(xiàn)中,你可以定義在調(diào)用目標(biāo)方法之前和之后要執(zhí)行的邏輯。

using Castle.DynamicProxy;  

  

public class MyInterceptor : IInterceptor  

{  

    public void Intercept(IInvocation invocation)  

    {  

        // 在調(diào)用目標(biāo)方法之前執(zhí)行的邏輯  

        Console.WriteLine("Before method: " + invocation.Method.Name);  

  

        // 調(diào)用目標(biāo)方法  

        invocation.Proceed();  

  

        // 在調(diào)用目標(biāo)方法之后執(zhí)行的邏輯  

        Console.WriteLine("After method: " + invocation.Method.Name);  

    }  

}

4. 創(chuàng)建代理并調(diào)用方法

最后,你需要使用ProxyGenerator類來創(chuàng)建MyService的代理實(shí)例,并指定攔截器。然后,你可以像使用普通對象一樣調(diào)用代理的方法,但攔截器中的邏輯會在調(diào)用發(fā)生時執(zhí)行。

using Castle.DynamicProxy;  

  

public class Program  

{  

    public static void Main(string[] args)  

    {  

        var generator = new ProxyGenerator();  

        var interceptor = new MyInterceptor();  

  

        // 創(chuàng)建MyService的代理實(shí)例,并指定攔截器  

        var proxy = generator.CreateInterfaceProxyWithTarget<IMyService>(  

            new MyService(), interceptor);  

  

        // 調(diào)用代理的方法,攔截器中的邏輯將被執(zhí)行  

        proxy.PerformAction();  

    }  

}

注意,上面的示例使用了接口代理(CreateInterfaceProxyWithTarget),這意味著你的目標(biāo)類必須實(shí)現(xiàn)一個或多個接口。如果你想要代理一個類而不是接口,你可以使用CreateClassProxyWithTarget方法(但這通常用于需要代理非虛方法或字段的場景,且要求目標(biāo)類是可繼承的)。

IOC中使用 Castle DynamicProxy

由于IOC容器(如Microsoft的IServiceCollectionIServiceProvider)通常不直接支持AOP,所以用 Autofac
1. 安裝必要的 NuGet 包

首先,確保你的項(xiàng)目中安裝了以下 NuGet 包:

Install-Package Autofac

Install-Package Autofac.Extensions.DependencyInjection

Install-Package Autofac.Extras.DynamicProxy

Install-Package Castle.Core

2. 創(chuàng)建服務(wù)接口和實(shí)現(xiàn)類

    public class User

    {

        public long Id { get; set; }


        public string Name { get; set; }


        public long CreateUserId { get; set; }


        public string CreateUserName { get; set; }


        public DateTime CreateTime { get; set; }


        public long UpdateUserId { get; set; }


        public string UpdateUserName { get; set; }


        public DateTime UpdateTime { get; set; }

    }    


    public interface IUserService

    {

        void Test();


        Task<int> TaskTest();


        void Add(User user);


       void Update(User user);

    }



    public class UserService : IUserService

    {

        public void Test()

        {

            Console.WriteLine("Test");

        }


        public async Task<int> TaskTest()

        {

            await Console.Out.WriteLineAsync("TaskTest");

            return 1;

        }


        public void Add(User user)

        {

            Console.WriteLine(user.CreateUserId);

            Console.WriteLine(user.CreateUserName);

        }


        public void Update(User user)

        {

            Console.WriteLine(user.UpdateUserId);

            Console.WriteLine(user.UpdateUserName);

        }

    }


    [ApiController]

    [Route("[controller]")]

    public class UserController : ControllerBase

    {

        readonly IUserService _userService;


        public UserController(IUserService userService)

        {

            _userService = userService;

        }        


        [HttpGet]

        [Route("/taskTest")]

        public async Task<string> TaskTest()

        {

            await _userService.TaskTest();

            return "ok";

        }


        [HttpGet]

        [Route("/test")]

        public string Test()

        {

            _userService.Test();

            return "ok";

        }


        [HttpGet]

        [Route("/add")]

        public string Add()

        {

            _userService.Add(new Model.User { Name = "張三" });

            return "ok";

        }



        [HttpGet]

        [Route("/update")]

        public string Update()

        {

            _userService.Update(new Model.User { Name = "張三" });

            return "ok";

        }

    }

3. 創(chuàng)建攔截器類

創(chuàng)建一個實(shí)現(xiàn) IInterceptor 接口的攔截器類 LoggingInterceptor,用于攔截方法調(diào)用并添加日志記錄:

public class LoggingInterceptor : IInterceptor

{

    public void Intercept(IInvocation invocation)

    {

        Console.WriteLine($"Before executing: {invocation.Method.Name}");


        invocation.Proceed(); // 調(diào)用原始方法


        Console.WriteLine($"After executing: {invocation.Method.Name}");

    }

}

4. 配置 Autofac 容器

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //使用Autofac

                        .ConfigureContainer<ContainerBuilder>(autofacBuilder =>

                        {

                       

                            autofacBuilder.RegisterType<LoggingInterceptor>();

                                             

                            autofacBuilder.RegisterType<UserService>().As<IUserService>    ().SingleInstance().AsImplementedInterfaces()    

                            .EnableInterfaceInterceptors() // 啟用接口攔截器

                            .InterceptedBy(typeof(LoggingInterceptor)); //指定攔截器

                        });

與Autofac集成時,配置攔截器主要有兩種方式

使用 InterceptAttribute 特性

這種方式通過在接口或類上添加[Intercept(typeof(YourInterceptor))]特性來指定攔截器。然后,在Autofac注冊時,啟用接口或類的攔截器。(通常不推薦在類上直接添加,因?yàn)檫@會使類與Autofac緊密耦合)

 [Intercept(typeof(UserAutoFillInterceptor))]

 public class UserService : IUserService

{  

     public void Test()

     {

        Console.WriteLine("Test");

     } 

}


autofacBuilder.RegisterType<UserService>().As<IUserService>().EnableInterfaceInterceptors() // 啟用接口攔截器

使用 InterceptedBy() 方法

這種方式不依賴于[Intercept]特性,而是在注冊服務(wù)時直接使用InterceptedBy()方法來指定攔截器。

                            autofacBuilder.RegisterType<UserService>().As<IUserService>()    

                            .EnableInterfaceInterceptors() // 啟用接口攔截器

                            .InterceptedBy(typeof(LoggingInterceptor)); //指定攔截器

實(shí)現(xiàn)事務(wù)管理

攔截器基類

    /// <summary>

    /// 攔截基類

    /// </summary>

    /// <typeparam name="T"></typeparam>

    public abstract class BaseInterceptor<T> : IInterceptor

    {

        protected readonly ILogger<T> _logger;

        public BaseInterceptor(ILogger<T> logger)

        {

            _logger = logger;

        }


        /// <summary>

        /// 攔截方法

        /// </summary>

        /// <param name="invocation"></param>

        public virtual void Intercept(IInvocation invocation)

        {

            try

            {

                Method = invocation.MethodInvocationTarget ?? invocation.Method;

                InterceptHandle(invocation);

            }

            catch (Exception ex)

            {

                _logger.LogError(ex, ex.Message);

                throw ex;

            }         

        }


        /// <summary>

        /// 攔截處理

        /// </summary>

        /// <param name="invocation"></param>

        public abstract void InterceptHandle(IInvocation invocation);


        protected MethodInfo Method{ get; set; }


        public static bool IsAsyncMethod(MethodInfo method)

        {

            return (method.ReturnType == typeof(Task) ||

                (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))

            );

        }

}

事務(wù)特性:用來判斷是否需要事務(wù)管理的

    /// <summary>

    /// 事務(wù)特性

    /// </summary>

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]

    public class TransactionalAttribute : Attribute

    {

        public TransactionalAttribute()

        {

            Timeout = 60;

        }


        /// <summary>

        /// 

        /// </summary>

        public int Timeout { get; set; }


        /// <summary>

        /// 事務(wù)隔離級別

        /// </summary>

        public IsolationLevel IsolationLevel { get; set; }


        /// <summary>

        /// 事務(wù)傳播方式

        /// </summary>

        public Propagation Propagation { get; set; }

    }


    /// <summary>

    /// 事務(wù)傳播方式

    /// </summary>

    public enum Propagation

    {

        /// <summary>

        /// 默認(rèn):如果當(dāng)前沒有事務(wù),就新建一個事務(wù),如果已存在一個事務(wù)中,加入到這個事務(wù)中。

        /// </summary>

        Required = 0,


        /// <summary>

        /// 使用當(dāng)前事務(wù),如果沒有當(dāng)前事務(wù),就拋出異常

        /// </summary>

        Mandatory = 1,


        /// <summary>

        /// 以嵌套事務(wù)方式執(zhí)行

        /// </summary>

        Nested = 2,

    }


事務(wù)攔截器:處理事務(wù)的

    /// <summary>

    /// 事務(wù)攔截器

    /// </summary>

    public class TransactionalInterceptor : BaseInterceptor<TransactionalInterceptor>

    {

        public TransactionalInterceptor(ILogger<TransactionalInterceptor> logger) : base(logger)

        {


        }


        public override void InterceptHandle(IInvocation invocation)

        {

            

            if (Method.GetCustomAttribute<TransactionalAttribute>(true) == null && Method.DeclaringType?.GetCustomAttribute<TransactionalAttribute>(true) == null)

            {

                invocation.Proceed();

            }

            else

            {

                try

                {

                    Console.WriteLine("開啟事務(wù)");


                    //執(zhí)行方法

                    invocation.Proceed();


                    // 異步獲取異常,先執(zhí)行

                    if (IsAsyncMethod(invocation.Method))

                    {

                        var result = invocation.ReturnValue;

                        if (result is Task)

                        {

                            Task.WaitAll(result as Task);

                        }

                    }


                    Console.WriteLine("提交事務(wù)");

                }

                catch (Exception ex)

                {

                    Console.WriteLine("回滾事務(wù)");

                    _logger.LogError(ex, ex.Message);

                    throw ex;

                }

            }

        }

    }


接口上加入事務(wù)特性

    //[Transactional]

    public class UserService : IUserService

    {


        [Transactional]

        public void Test()

        {

            Console.WriteLine("Test");

        }

    }


注入IOC

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())

                        .ConfigureContainer<ContainerBuilder>(autofacBuilder =>

                        {

                            autofacBuilder.RegisterType<TransactionalInterceptor>();                                      

                            autofacBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance().AsImplementedInterfaces()

                            .EnableInterfaceInterceptors()

                            .InterceptedBy(typeof(TransactionalInterceptor));

                        });


測試

實(shí)現(xiàn)用戶自動填充

上下戶用戶

    public interface IHttpContextUser

    {

         long UserId { get; }


         string UserName { get;}

    }



    public class HttpContextUser : IHttpContextUser

    {

        private readonly IHttpContextAccessor _accessor;

        public HttpContextUser(IHttpContextAccessor accessor)

        {

            _accessor = accessor;

        }

        public long UserId

        {

            get

            {

                return 1; //這里暫時是寫死的

                if (int.TryParse(_accessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Sid), out var userId))

                {

                    return userId;

                }

                return default;

            }

        }


        public string UserName

        {

            get

            {

                return "admin"; //這里暫時是寫死的

                return _accessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Name) ?? "";

            }

        }

    }



注入IOC

           builder.Services.AddHttpContextAccessor();

           builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())

                        .ConfigureContainer<ContainerBuilder>(autofacBuilder =>

                        {

                       

                            autofacBuilder.RegisterType<HttpContextUser>().As<IHttpContextUser>().SingleInstance().AsImplementedInterfaces();

                            autofacBuilder.RegisterType<UserAutoFillInterceptor>();

                       

                       

                            autofacBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance().AsImplementedInterfaces()

                            .EnableInterfaceInterceptors()

                            .InterceptedBy(typeof(UserAutoFillInterceptor));

                        });


用戶自動攔截器:處理用戶填充的

    /// <summary>

    /// 用戶自動填充攔截器

    /// </summary>

    public class UserAutoFillInterceptor : BaseInterceptor<UserAutoFillInterceptor>

    {

        private readonly IHttpContextUser _user;

        public UserAutoFillInterceptor(ILogger<UserAutoFillInterceptor> logger,IHttpContextUser user) : base(logger)

        {

            _user = user;

        }


        public override void InterceptHandle(IInvocation invocation)

        {

            //對當(dāng)前方法的特性驗(yàn)證

            if (Method.Name?.ToLower() == "add" || Method.Name?.ToLower() == "update")

            {

                if (invocation.Arguments.Length == 1 && invocation.Arguments[0].GetType().IsClass)

                {

                    dynamic argModel = invocation.Arguments[0];

                    var getType = argModel.GetType();

                    if (Method.Name?.ToLower() == "add")

                    {

                        if (getType.GetProperty("CreateUserId") != null)

                        {

                            argModel.CreateUserId = _user.UserId;

                        }

                        if (getType.GetProperty("CreateUserName") != null)

                        {

                            argModel.CreateUserName = _user.UserName;

                        }

                        if (getType.GetProperty("CreateTime") != null)

                        {

                            argModel.CreateTime = DateTime.Now;

                        }

                     

                    }

                    if (getType.GetProperty("UpdateUserId") != null)

                    {

                        argModel.UpdateUserId = _user.UserId;

                    }

                    if (getType.GetProperty("UpdateUserName") != null)

                    {

                        argModel.UpdateUserName = _user.UserName;

                    }

                    if (getType.GetProperty("UpdateTime") != null)

                    {

                        argModel.UpdateTime = DateTime.Now;

                    }

                   

                    }

                invocation.Proceed();

            }

            else

            {

                invocation.Proceed();

            }

        }

    }


測試



該文章在 2024/9/13 9:24:52 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved