C#使用委託實現函式回撥,方法呼叫攔截

白码一号發表於2024-08-23

C#使用委託實現函式回撥,方法呼叫攔截

回撥方法、攔截方法定義

public class AopHelper
{
    public static async Task<T> ExecuteGenericMethod<T>(Task<T> returnValue, Action<T> callBackAction, Action<Exception> exceptionAction, Action finallyAction)
    {
        try
        {
            var result = await returnValue;
            callBackAction?.Invoke(result);
            return result;
        }
        catch (Exception ex)
        {
            exceptionAction?.Invoke(ex);
            return default;
        }
        finally
        {
            finallyAction?.Invoke();
        }
    }

    public static object CallGenericMethod(IInvocation invocation, Action<object> callBackAction, Action<Exception> exceptionAction, Action finallyAction)
    {
        return typeof(AopHelper)
        .GetMethod("ExecuteGenericMethod", BindingFlags.Public | BindingFlags.Static)
        .MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
        .Invoke(null, new object[] { invocation.ReturnValue, callBackAction, exceptionAction, finallyAction });
    }
}

下面是具體實現 方法執行完 回撥函式 異常函式 資源釋放函式

public class Test01
{
    // 任務方法:非同步執行某些操作
    public static async Task<int> DoSomethingAsync(int a)
    {
        await Task.Delay(1000); // 模擬非同步操作

        //Random rnd = new Random();
        int number = a;

        if (number < 5)
        {
            throw new InvalidOperationException("發生了一個隨機異常!");
        }

        return number;
    }

    // 主方法:呼叫 ExecuteGenericMethod<T> 並提供回撥和異常處理
    public static async Task Main(int a)
    {
        // 呼叫 ExecuteGenericMethod 並處理任務的成功、異常和最終操作
        int result = await ExecuteGenericMethod(
            DoSomethingAsync(a),
            success => Console.WriteLine($"成功執行,結果為: {success}"),      // 成功回撥
            ex => Console.WriteLine($"處理異常: {ex.Message}"),                // 異常處理
            () => Console.WriteLine("清理操作:無論是否成功都要執行的程式碼")      // 最終執行
        );

        Console.WriteLine($"最終返回的結果: {result}");
    }

    // 泛型方法:執行非同步任務並處理回撥、異常和清理操作
    public static async Task<T> ExecuteGenericMethod<T>(
        Task<T> returnValue,
        Action<T> callBackAction,
        Action<Exception> exceptionAction,
        Action finallyAction)
    {
        try
        {
            var result = await returnValue;
            callBackAction?.Invoke(result);
            return result;
        }
        catch (Exception ex)
        {
            exceptionAction?.Invoke(ex);
            return default;
        }
        finally
        {
            finallyAction?.Invoke();
        }
    }
}
public class Test02
{
    public static object CallGenericMethod(IInvocation invocation, Action<object> callBackAction, Action<Exception> exceptionAction, Action finallyAction)
    {
        return typeof(AopHelpers)
        .GetMethod("ExecuteGenericMethod", BindingFlags.Public | BindingFlags.Static)
        .MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
        .Invoke(null, new object[] { invocation.ReturnValue, callBackAction, exceptionAction, finallyAction });
    }

    public static async Task Main(int a)
    {
        AopHelpers aopHelper = new AopHelpers();
        int s = await ExecuteGenericMethod<int>(aopHelper.DoSomethingAsync(a), success => aopHelper.CallBackAction(success), ex => aopHelper.ExceptionFunction01(ex), () => aopHelper.ActionFunction01(a));
        Console.WriteLine(s);
    }

    public static async Task<T> ExecuteGenericMethod<T>(Task<T> returnValue, Action<T> callBackAction, Action<Exception> exceptionAction, Action finallyAction)
    {
        try
        {
            var result = await returnValue;
            callBackAction?.Invoke(result);
            return result;
        }
        catch (Exception ex)
        {
            exceptionAction?.Invoke(ex);
            return default;
        }
        finally
        {
            finallyAction?.Invoke();
        }
    }

    public async Task<int> DoSomethingAsync(int a)
    {
        if (a < 5)
        {
            throw new InvalidOperationException("發生了一個隨機異常!");
        }

        Console.WriteLine("主方法執行完 a:" + a);
        //return Task.FromResult(a);  返回異常直接拋到最外層
        return a + 2;
    }


    public Action<int> CallBackAction(int a)
    {
        Console.WriteLine("我是方法執行完的回撥函式 a:" + a);
        //return a => { a = a + 6; };
        return a => a = a + 6;
    }

    public Action<Exception> ExceptionFunction01(Exception ex)
    {
        Console.WriteLine("方法執行報錯 值為:" + ex.Message);
        return ex => Console.WriteLine($"處理異常: {ex.Message}");
    }

    public Action ActionFunction01(int a)
    {
        Console.WriteLine("資源使用完畢清空");
        return () => a = 0;
    }
}

下面是具體方法呼叫前的攔截 和引數校驗

    public interface IMyService
    {
        Task<int> DoSomethingAsync();
    }

    public class MyService : IMyService
    {
        public async Task<int> DoSomethingAsync()
        {
            await Task.Delay(100); // 模擬非同步操作
            //return new List<int> {1,2,3 }; // 返回一些結果
            return 1; // 返回一些結果 這裡是int型別會報異常  返回object正常
        }
    }

    public static class IInvocationProgram
    {
        public static object CallGenericMethod(IInvocation invocation, Action<object> callBackAction, Action<Exception> exceptionAction, Action finallyAction)
        {
            return typeof(IInvocationProgram)
                .GetMethod("ExecuteGenericMethod", BindingFlags.Public | BindingFlags.Static)
                .MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
                .Invoke(null, new object[] { invocation.ReturnValue, callBackAction, exceptionAction, finallyAction });
        }

        public static T ExecuteGenericMethod<T>(Task<T> returnValue, Action<T> callBackAction, Action<Exception> exceptionAction, Action finallyAction)
        {
            try
            {
                // 模擬等待任務完成並返回結果
                var result = returnValue.Result;
                callBackAction?.Invoke(result);
                return result;
            }
            catch (Exception ex)
            {
                exceptionAction?.Invoke(ex);
                return default(T);
            }
            finally
            {
                finallyAction?.Invoke();
            }
        }
    }

    public class MyInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            try
            {
                // 先呼叫原始方法
                invocation.Proceed();

                // 如果返回值是泛型任務,使用 CallGenericMethod
                if (invocation.Method.ReturnType.IsGenericType && invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
                {
                    var result = IInvocationProgram.CallGenericMethod(invocation,
                        callBackAction: (obj) => Console.WriteLine($"回撥執行,結果為:{obj}"),
                        exceptionAction: (ex) => Console.WriteLine($"異常捕獲:{ex.Message}"),
                        finallyAction: () => Console.WriteLine("最終執行"));

                    Console.WriteLine($"動態呼叫的結果: {result}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"攔截器捕獲到異常:{ex.Message}");
            }
        }

        public static void Main()
        {
            // 建立代理生成器
            var proxyGenerator = new ProxyGenerator();

            // 建立 MyService 的代理物件,並注入攔截器
            var myService = proxyGenerator.CreateInterfaceProxyWithTarget<IMyService>(new MyService(), new MyInterceptor());

            // 呼叫方法,將觸發攔截器
            var task = myService.DoSomethingAsync();

            task.Wait(); // 等待非同步任務完成
        }
    }

相關文章