首页 > 编程语言 >C#使用委托实现函数回调,方法调用拦截

C#使用委托实现函数回调,方法调用拦截

时间:2024-08-23 09:06:47浏览次数:8  
标签:调用 return C# Task ex Action 拦截 public result

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(); // 等待异步任务完成
        }
    }

 

标签:调用,return,C#,Task,ex,Action,拦截,public,result
From: https://www.cnblogs.com/OneSeting/p/18375167

相关文章

  • qt5.14.2 MSVC opencv(不结合vs)路径添加问题 测试通过
     不换行写法1win32:CONFIG(release,debug|release):LIBS+=-LG:/opencv4.4.0/opencv4.4_vs_msvc19_qt6.5/x64/vc17/lib/-lopencv_aruco440-lopencv_bgsegm440-lopencv_bioinspired440-lopencv_calib3d440-lopencv_ccalib440-lopencv_core440-lopencv_cvv440-lopen......
  • Object类
    8.3Object类目录8.3Object类8.3.1Object类简介Object类的结构图(Object提供了11个方法)clone()getClass()toString()finalize()equals()hashCode()wait()notify()notifyAll()8.3.2Object类的常用方法toString方法equals方法8.3.1Object类简介Object类是Javajava.lang包下......
  • 高手过招--论TCP之粘包的解决方法
    粘包,就是查询的内容都粘到一起了,比如客户端发送ipconfig/all命令到服务端,客户端的只收取一次服务端的返回结果,且设置为一次只能取出1024个字节的数据。假设ipconfig/all这条命令的返回结果大小是2048个字节,这就意味着还有1024没有取出来,仍然会保存在客户端的缓存中。此时客户端......
  • 05-02 Relationships Between Objects(对象之间的关系 )
    RelationshipsBetweenObjects(对象之间的关系)XPOsupportsthreetypesofrelationshipsbetweenobjects.Thetypeofarelationshipthatiscreateddependsuponhowrelatedobjectsaredefined.XPO支持对象之间的三种类型的关系。创建的关系类型取决于相关对......
  • 05-03 Map Persistent Objects to Database Views(将持久对象映射到数据库视图 )
    MapPersistentObjectstoDatabaseViews(将持久对象映射到数据库视图)CreateaPersistentClass(创建持久类)Createapersistentclass.Theclassnameshouldmatchtheviewname.创建一个持久类。类名应与视图名匹配。AssignthePersistentattributetotheper......
  • 05-04 Basics of Creating Persistent Objects for Existing Data Tables(为现有数据表
    BasicsofCreatingPersistentObjectsforExistingDataTables(为现有数据表创建持久对象的基础知识)ToaccessanexistingdatatableinadatabaseandworkwithitusingthefunctionalityprovidedbyeXpressPersistentObjects(XPO),youneedtocreateap......
  • C语言-数组名与&数组名的细节注意
    这篇博客将通过整型数组、字符数组、字符串放在数组中、以及二维数组的数组名与&数组名和各类特殊情况的题目讲解来使得我们对于指针与数组名具有更加深刻的了解。注意:sizeof(数组名)-数组名表示整个数组的-计算的是整个数组的大小&数组名-数组名表示整个数组,取出的是整......
  • 05-01 Create a Persistent Object(创建持久对象)
    CreateaPersistentObject(创建持久对象)TheXPOORMcanloadandsavetoadatastoreonlypersistentobjects.XPOORM只能加载持久对象并将其保存到数据存储中。Youmakeyourbusinessobjectspersistentinanyofthefollowingways:您可以通过以下任何方式......
  • 什么?!90%的ThreadLocal都在滥用或错用!
    最近在看一个系统代码时,发现系统里面在使用到了ThreadLocal,乍一看,好像很高级的样子。我再仔细一看,这个场景并不会存在线程安全问题,完全只是在一个方法中传参使用的啊!(震惊)难道是我水平太低,看不懂这个高级用法?经过和架构师请教和确认,这完全就是一个ThreadLocal滥用的典型案例啊!......
  • 《机器学习》—— AUC评估指标
    文章目录一、什么是AUC?1、什么是ROC曲线?2、ROC曲线的绘制二、如何计算AUC的值三、代码实现AUC值的计算四、AUC的优缺点一、什么是AUC?机器学习中的AUC(AreaUndertheCurve)是一个重要的评估指标,特别是在二分类问题中。AUC特指ROC曲线(ReceiverOperatingCharacterist......