C#利用过滤器实现多系统接入数据源系统,数据源更新后通知其他系统

特点:在不改系统主线代码的前提下,可实现主数据更改,第三方数据同步更改。
想法初衷:举个最简单的例子,公司系统接入多个第三方系统时,人员主要数据在我公司手上,但是人员数据是不常更新的,所以不可能实时更新,如果用计划任务每天更新一次也是很low的解决方案,所以产生现有想法,公司的系统人员更改后调用需要同步数据的第三方接口,让第三方实时与主数据源保持一致。

原理:通过过滤器获取返回值,如果返回的是成功,则通过反射执行事先写好的调用第三方同步接口的dll。
很简单的一个demo,废话不多说,直接上代码。。。

在方法前加上过滤器

[ExtendService]
public ActionResult Update(User user)
{
    ResponseContext<string> ret = new ResponseContext<string>();
    //TODO Update
    return Json(ret,JsonRequestBehavior.AllowGet);
}

过滤器
path为配置的接入第三方系统接口配置文件路径,每新增一个需要同步数据的第三方,写好调用第三方提供数据同步接口的dll后直接在配置文件中配置。

public class ExtendServiceAttribute : FilterAttribute, IActionFilter
{
     public void OnActionExecuted(ActionExecutedContext filterContext)
     {
         try
         {
            var result = (JsonResult)filterContext.Result;
            var parameters = filterContext.ActionDescriptor.GetParameters();
            string newData = "";
            if(parameters.Length > 0)
            {
                var itemType = parameters[0].ParameterType;
                PropertyInfo[] infos = itemType.GetProperties();
                Dictionary<string, string> parmsObj = new Dictionary<string, string>();
                foreach (PropertyInfo info in infos)
                {
                    if (info.CanRead)
                    {
                        var propertyValue = filterContext.Controller.ValueProvider.GetValue(info.Name);
                        if (!parmsObj.ContainsKey(info.Name))
                        {
                            parmsObj.Add(info.Name, propertyValue.AttemptedValue); 
                        }
                    }
                }
                //TODO
                //newData = 根据主键去数据库中查找更新的数据
            }
            var responseContext = result.Data as ResponseContext<string>;
            if (responseContext.Head.IsSuccess)
            {
                ExtendService extend = new ExtendService();
                string path = ConfigurationManager.AppSettings["ExtendService"];
                extend.Excute(HttpContext.Current.Server.MapPath("~" + path), "12345", newData);
            }
         }
         catch (Exception ex)
         {
             
         }
     }

     public void OnActionExecuting(ActionExecutingContext filterContext)
     {
         
     }
 }

ResponseContext是自己封装的一个响应实体。

public class ResponseContext<T>
{
    /// <summary>
    /// 响应头
    /// </summary>
    public Head Head { get; set; }
    /// <summary>
    /// 响应体
    /// </summary>
    public T Content { get; set; }

    public ResponseContext()
    {
        Head = new Head();
        Content = default(T);
    }
}

动态调用第三方接口代码

   /// <summary>
   /// 
   /// </summary>
   /// <param name="extendServerPath">第三方接入配置文件</param>
   /// <param name="id">修改的id</param>
   /// <param name="newData">返回修改后的数据,json字符串</param>
   public delegate void Handler(string extendServerPath, string id, string newData);
   public class ExtendService
   {
       public event Handler UpdateEvent;
       
       public void Excute(string extendServerPath, string id, string newData)
       {
           UpdateEvent += LoadService;
           UpdateEvent?.Invoke(extendServerPath, id, newData);
       }

       public void LoadService(string extendServerPath, string id, string newData)
       {
           XmlDocument xml = new XmlDocument();
           xml.Load(extendServerPath);

           XmlNode data = xml.SelectSingleNode("Service");
           XmlNodeList nodeList = data.SelectNodes("Extend");

           List<XmlNode> list = new List<XmlNode>();
           foreach (XmlNode node in nodeList)
           {
               XmlElement el = (XmlElement)node;
               string type = el.Attributes["type"].Value.ToLower();
               if (type == ExtendServiceType.Update.ToString().ToLower())
                   list.Add(node);
           }

           foreach(XmlNode node in list)
           {
               XmlNodeList childs = node.ChildNodes;
               string path = "";
               string classFullName = "";
               string method = "";
               foreach (XmlNode child in childs)
               {
                   XmlElement el = (XmlElement)child;
                   if (el.Name == "Path")
                       path = el.InnerText;
                   else if(el.Name == "ClassFullName")
                       classFullName = el.InnerText;
                   else if (el.Name == "Method")
                       method = el.InnerText;
               }
               ArrayList arrayList = new ArrayList(); 
               arrayList.Add(id);
               arrayList.Add(newData);
               InvokeService(path, classFullName, method, arrayList);
           }
       }

       private void InvokeService(string path,string classFullName,string method, ArrayList paramArr)
       {
           try
           {
               Assembly assembly = Assembly.LoadFile(path);
               var t = assembly.GetType(classFullName);
               object obj = Activator.CreateInstance(t);
               MethodInfo methodInfo = t.GetMethod(method);
               methodInfo.Invoke(obj, paramArr.ToArray());
           }
           catch (Exception ex)
           {
               throw ex;
           }
       }
   }

服务配置文件,每新增一个第三方就增加一个Extend节点,type标识用途

<?xml version="1.0" encoding="utf-8" ?>
<Service>
  <Extend type="Update">
    <Path>D:/Projects/UpdateNotifiy/bin/Debug/UpdateNotifiy.dll</Path>
    <ClassFullName>UpdateNotifiy.NotifyTest</ClassFullName>
    <Method>Test</Method>
  </Extend>
</Service>

下面这个是测试第三方接口demo dll

namespace UpdateNotifiy
{
    public class NotifyTest
    {
        public void Test(string id)
        {
            public void Test(string id, string newData)
	        {
	            var d = new { Id = id, NewData = newData };
	            var data = JsonConvert.SerializeObject(d);
	            HttpContent content = new StringContent(data);
	            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
	            using (HttpClient httpClient = new HttpClient())
	            {
	                string responseJson = httpClient.PostAsync("http://localhost:56684/api/Default/TestNotify", content).Result.Content.ReadAsStringAsync().Result;
	            }
	        }
        }
    }
}

第一次写博客,大佬勿喷,给需要的童鞋参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值