特点:在不改系统主线代码的前提下,可实现主数据更改,第三方数据同步更改。
想法初衷:举个最简单的例子,公司系统接入多个第三方系统时,人员主要数据在我公司手上,但是人员数据是不常更新的,所以不可能实时更新,如果用计划任务每天更新一次也是很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;
}
}
}
}
}
第一次写博客,大佬勿喷,给需要的童鞋参考。