using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Campaign.Commons.ConstParam;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Campaign.Commons.ExtMethod
{
public static class JsonParamsHelper
{
/// <summary>
/// 替换类中同名的属性的值,并返回填充后的类
/// </summary>
/// <typeparam name="T">要填充的类型</typeparam>
/// <param name="frameobj">要填充的参数</param>
/// <param name="parms">包含对象的参数的一维json</param>
/// <param name="extendsParams">扩展参数,针对params中的模板进行替换($索引$)</param>
/// <returns>填充后的frameobj</returns>
public static T FrameFilling<T>(this T frameobj, string parms, params object[] extendsParams)
where T : class, new()
{
try
{
var pas = JsonConvert.DeserializeObject<dynamic>(parms);
return LoopFilling(frameobj, pas, extendsParams);
}
catch
{
return null;
}
}
#region 简化工具
private static T LoopFilling<T, TP>(T obj, TP param, object[] extparams = null, ReplaceModeEnum replaceMode = ReplaceModeEnum.FullPettern) where T : new()
where TP : JObject
{
try
{
foreach (var oo in obj.GetType().GetProperties())
{
if (oo.PropertyType.IsValueType || oo.PropertyType.Name == "String")
{
var month = oo.GetSetMethod();
if (param[oo.Name] == null || param[oo.Name].Type == JTokenType.Array ||
param[oo.Name].Type == JTokenType.Object)
continue;
if (!month.IsPublic || param[oo.Name] == null) continue;
month.Invoke(obj,
new[]
{
param[oo.Name].PartternRep(RegexPatterns.WECHAT_TEMP_MESSAGE_ARGS_PATTERN, extparams,
oo.PropertyType)
});
}
else if (oo.PropertyType.GetInterface("IEnumerable") != null)
{
//是集合类型
//泛型集合
var _enum = oo.PropertyType;
if (_enum.GetInterface("IList") != null)
{
//判断参数中的该参数是否为数组
if (param[oo.Name] != null && param[oo.Name].Type == JTokenType.Array)
{
//创建泛型类型
var tps = _enum.GetGenericArguments()[0];
if (tps.IsGenericType)
throw new Exception("目前泛型只支持一层嵌套!");
var addmethod = _enum.GetMethod("Add");
var list = oo.GetValue(obj);
if (list == null)
{
var tp = typeof(List<>);
var gtp = tp.MakeGenericType(tps);
list = Activator.CreateInstance(gtp); //只允许一层泛型,泛型嵌套不给予考录。
oo.GetSetMethod().Invoke(obj, new[] { list });
}
//o可能是基础类型,或者是Object
//如果是基础类型,直接加,如果是Object,还需要反射,获取Object中的值
if (tps.IsValueType || tps.Name == "String")
{
foreach (var ppp in param[oo.Name])
{
addmethod.Invoke(list,
new[]
{
ppp.PartternRep(RegexPatterns.WECHAT_TEMP_MESSAGE_ARGS_PATTERN,
extparams, tps)
});
}
}
else if (tps.IsClass)
{
var undertypeproperty = tps.GetProperties();
foreach (var o in param[oo.Name])
{
var udi = Activator.CreateInstance(tps);
foreach (var i in undertypeproperty)
{
if (i.PropertyType.IsValueType || i.PropertyType.Name == "String")
{
i.GetSetMethod()
.Invoke(udi,
new[]
{
o[i.Name].PartternRep(
RegexPatterns.WECHAT_TEMP_MESSAGE_ARGS_PATTERN,
extparams, i.PropertyType)
});
}
else
{
LoopFilling(udi, (JObject)o, extparams);
}
}
addmethod.Invoke(list, new[] { udi });
}
}
}
}
else if (_enum.GetInterface("IDictionary") != null)
{
if (param[oo.Name] == null || param[oo.Name].Type != JTokenType.Object)
continue;
var gentypes = _enum.GetGenericArguments();
//如果Key不是String类型的话抛出异常
if (gentypes[0].Name != "String")
throw new Exception("Key只能为string类型。");
dynamic idic = oo.GetValue(obj);
if (idic == null)
{
var dct = typeof(Dictionary<,>);
idic = Activator.CreateInstance(dct.MakeGenericType(_enum.GetGenericArguments()));
oo.GetSetMethod().Invoke(obj, new object[] { idic });
}
foreach (var n in (JObject)param[oo.Name])
{
dynamic key = n.Key;
dynamic value = idic.ContainsKey(n.Key)
? idic[n.Key]
: Activator.CreateInstance(gentypes[1]);
LoopFilling(value, (JObject)n.Value, extparams);
if (idic.ContainsKey(n.Key))
idic[key] = value;
else
idic.Add(key, value);
}
}
}
else if (oo.PropertyType.IsClass)
{
if (param[oo.Name] == null || param[oo.Name].Type != JTokenType.Object)
continue;
var _obj = oo.GetValue(obj);
if (_obj == null)
{
_obj = Activator.CreateInstance(oo.PropertyType);
oo.GetSetMethod().Invoke(obj, new[] { _obj });
}
LoopFilling(oo.GetValue(_obj), (JObject)param[oo.Name], extparams);
}
}
}
catch (Exception e)
{
e.Log("Json填充实体失败:");
}
return obj;
}
private static object PartternRep(this JToken token, string targ, object[] parms, Type tagType, ReplaceModeEnum replaceMode = ReplaceModeEnum.FullPettern)
{
//根据匹配的模式进行字符串处理
if (!tagType.IsValueType && tagType.Name != "String")
throw new Exception("T只能是简单类型(值类型或String)!");
if (!Regex.IsMatch(token.Value<string>(), targ))
return Convert.ChangeType(token, tagType);
if (parms == null)
{
throw new Exception("没有提供需要的参数");
}
//如果多种匹配方式,则优先级如下:NamingPettern>PartPettern>FullPettern
string pattern = targ;
switch (replaceMode)
{
case ReplaceModeEnum.FullPettern:
if (Regex.IsMatch(targ, "\^\w+\$"))
break;
pattern = string.Concat("^", targ, "$");
break;
case ReplaceModeEnum.NamingPettern://以后再做吧
break;
case ReplaceModeEnum.PartPettern:
if (!Regex.IsMatch(targ, "\^\w+\$"))
break;
pattern = targ.Substring(1, targ.Length - 2);
break;
case (ReplaceModeEnum.FullPettern|ReplaceModeEnum.NamingPettern)://以后再做吧
/*
查看所有的参数,寻找类类型的参数,
*/
break;
case (ReplaceModeEnum.PartPettern | ReplaceModeEnum.NamingPettern)://以后再做吧
break;
case (ReplaceModeEnum.FullPettern | ReplaceModeEnum.PartPettern)://依然是PartPettern
if (!Regex.IsMatch(targ, "\^\w+\$"))
break;
pattern = targ.Substring(1, targ.Length - 2);
break;
}
var mtcs = Regex.Matches(token.Value<string>(), pattern,
RegexOptions.CultureInvariant);
var paridx = int.Parse(mtcs[0].Groups["rpidx"].Value);
if (paridx >= parms.Length || paridx < 0)
throw new Exception("动态参数索引越界!");
if (parms[paridx] == null)
throw new Exception("提供的参数不能为Null");
return Convert.ChangeType(parms[paridx], tagType);
}
public static bool IsAnonymousType(this Type tp)
{
return tp.Name.Contains("AnonymousType");
}
#endregion
}
}
//使用方法
public class a{
public string name{get;set;}
public string sex{get;set;}
}
a.FrameFilling("{"name":"张三"}")
a.name//等于张三