• c# 根据日志中的方法信息,反射再次执行相关方法


    场景:

    在实际的项目中,会遇到与第三方的接口互调,在这样的场景下,日志显得尤为重要。

    有这样一种情况,就是在请求第三方接口后,需要将请求的结果进行过滤处理,再持久化,这就需要服务中提供相关的服务方法来执行,如果执行异常,或是有错误,希望通过相关的后台界面,再次执行时,就可以将服务方法的相关信息记录,通过反射再次调用。

    方法类型

     public class ReflectionMethodInfo
        {
            public string AssemblyInfo { get; set; }
    
            public string TypeInfo { get; set; }
    
            public string MethodInfo { get; set; }
    
            public Type[] ParameterTypeInfo { get; set; }
    
            public object[] ParameterInfo { get; set; }
        }

    记录日志

    public class TxtHelper
        {
            static string txtPath
            {
                get
                {
                    return AppDomain.CurrentDomain.BaseDirectory + "log.txt";
                }
            }
    
            public static void writeTxt(object txt)
            {
                var text = string.Empty;
                if (typeof(ReflectionMethodInfo).IsInstanceOfType(txt))
                {
                    text = "【reflection】" + Newtonsoft.Json.JsonConvert.SerializeObject(txt) + "【reflection】";
                }
                else
                {
                    text = txt.ToString();
                }
    
                System.IO.File.AppendAllText(txtPath, text);
                System.IO.File.AppendAllText(txtPath, Environment.NewLine);
            }
    
            public static void writeMethod(Assembly assembly, MethodBase methodBase, object[] parameterInfo)
            {
                var reflectionMethodInfo = new ReflectionMethodInfo()
                {
                    AssemblyInfo = assembly.FullName,
                    TypeInfo = methodBase.DeclaringType.FullName,
                    MethodInfo = methodBase.Name,
                    ParameterTypeInfo = methodBase.GetParameters().Select(p => p.ParameterType).ToArray(),
                    ParameterInfo = parameterInfo
                };
                TxtHelper.writeTxt(reflectionMethodInfo);
    
            }
        }

    调用记录方法

    public void ParameterMethod(string parameter, TestParameters testParameters)
            {
                this.name = parameter;
    
                TxtHelper.writeTxt($"NetReflection.ParameterMethod({parameter},{testParameters}) 【EXEC】");
    
                TxtHelper.writeMethod(Assembly.GetExecutingAssembly(), MethodBase.GetCurrentMethod(), new object[] { parameter, testParameters });
            }
    

     反射执行

    static object DynamicExecMethod(string methodInfo)
            {
                var methodInfoObj = JsonConvert.DeserializeObject<ReflectionMethodInfo>(methodInfo);
    
                if (methodInfoObj == null)
                {
                    Console.WriteLine("methodInfoObj is null");
                    return null;
                }
    
                // 加载程序集
                var assembly = Assembly.Load(methodInfoObj.AssemblyInfo);
    
                // 获取类型
                var type = assembly.GetType(methodInfoObj.TypeInfo);
    
                // 创建实例 , 此方式要求实例类型必须有无参构造函数
                var instance = Activator.CreateInstance(type);
    
                // 加载方法
                var method = type.GetMethod(methodInfoObj.MethodInfo, methodInfoObj.ParameterTypeInfo);
    
                // 创建参数类型信息,JObject 转换成指定的参数类型
                var newParameters = new List<object>();
                var parameters = methodInfoObj.ParameterInfo;
                var declareParameters = method.GetParameters();
                var parameterIndex = 0;
                foreach (var parameter in declareParameters)
                {
                    var parameterType = parameter.ParameterType;
                    var newParameter = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(parameters[parameterIndex]), parameterType);
                    newParameters.Add(newParameter);
                    parameterIndex++;
                }
    
                // 执行方法
                var returnValue = method.Invoke(instance, newParameters.ToArray());
    
                return returnValue;
            }

    数据库表

    CREATE TABLE [dbo].[Application_Log](
        [Id] [uniqueidentifier] NOT NULL,
        [SerialNumber] [varchar](50) NULL,
        [Url] [varchar](4000) NULL,
        [Body] [nvarchar](max) NULL,
        [Result] [nvarchar](max) NULL,
        [Method] [nvarchar](max) NULL,
        [Mark] [nvarchar](max) NULL,
        [State] [bit] NOT NULL,
        [Action] [varchar](50) NOT NULL,
        [Type] [varchar](50) NULL,
        [CreateTime] [datetime] NOT NULL,
        [LogicDeleteFlag] [bit] NOT NULL,
     CONSTRAINT [PK_Api_Log] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'调用/请求/同步等操作接口' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Url'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'请求Body' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Body'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'请求结果' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Result'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'程序代码中相关方法信息,主要目的是为处理拉取类时,可以再次拉取。(拉取信息不仅仅是请求,还需要处理请求的结果)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Method'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'其它备注说明' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Mark'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'请求状态 成功、失败' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'State'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'具体操作,如第三方调用,拉取日志,拉取轨迹' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Action'
    GO
    
    EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'本次请求类型:ThirdRequest(第三方请求我方接口)、PullThird(拉取/请求 第三方信息)、PushThird(同步/推送 信息到第三方)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Application_Log', @level2type=N'COLUMN',@level2name=N'Type'
    GO
  • 相关阅读:
    ArcGIS api for javascript——合并切片和动态图层
    ArcGIS api for javascript——加入两个动态地图
    ArcGIS api for javascript——加入动态地图
    ArcGIS api for javascript——1,2,3综合
    ArcGIS api for javascript——加入地图并显示x,y坐标
    ArcGIS api for javascript——加入地图并显示当前地图范围
    ArcGIS api for javascript——创建地图
    Django框架(六):模型(二) 字段查询、查询集
    Django框架(五):模型(一) 定义属性
    Django框架(四):视图、模板
  • 原文地址:https://www.cnblogs.com/challengesoflife/p/14544587.html
Copyright © 2020-2023  润新知