using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using WalkingTec.Mvvm.Core.Extensions;
namespace WalkingTec.Mvvm.Core
{
///
/// 属性辅助类
///
public static class PropertyHelper
{
public static object GetExpressionRootObj(Expression expression)
{
if (expression == null)
{
return "";
}
Expression me = null;
LambdaExpression le = null;
if (expression is MemberExpression)
{
me = expression as MemberExpression;
}
if (expression is LambdaExpression)
{
le = expression as LambdaExpression;
if (le.Body is MemberExpression)
{
me = le.Body as MemberExpression;
}
if (le.Body is UnaryExpression)
{
me = (le.Body as UnaryExpression).Operand as MemberExpression;
}
}
while (me != null && me.NodeType == ExpressionType.MemberAccess)
{
Expression exp = (me as MemberExpression).Expression;
if (exp is MemberExpression)
{
me = exp as MemberExpression;
}
else if (exp is MethodCallExpression)
{
var mexp = exp as MethodCallExpression;
if (mexp.Method.Name == "get_Item")
{
object index = 0;
if (mexp.Arguments[0] is MemberExpression)
{
var obj = ((mexp.Arguments[0] as MemberExpression).Expression as ConstantExpression).Value;
index = obj.GetType().GetField((mexp.Arguments[0] as MemberExpression).Member.Name).GetValue(obj);
}
else
{
index = (mexp.Arguments[0] as ConstantExpression).Value;
}
me = mexp.Object as MemberExpression;
}
}
else
{
me = exp;
break;
}
}
if(me.NodeType == ExpressionType.Constant)
{
return (me as ConstantExpression)?.Value;
}
return null;
}
public static Func GetPropertyExpression(Type objtype, string property)
{
property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty);
List level = new List();
if (property.Contains('.'))
{
level.AddRange(property.Split('.'));
}
else
{
level.Add(property);
}
var pe = Expression.Parameter(objtype);
var member = Expression.Property(pe, objtype.GetSingleProperty(level[0]));
for (int i = 1; i < level.Count; i++)
{
member = Expression.Property(member, member.Type.GetSingleProperty(level[i]));
}
return Expression.Lambda>(member, pe).Compile();
}
///
/// 获取属性名
///
/// 属性表达式
/// 是否获取全部级别名称,比如a.b.c
/// 属性名
public static string GetPropertyName(this Expression expression, bool getAll = true)
{
if (expression == null)
{
return "";
}
MemberExpression me = null;
LambdaExpression le = null;
if (expression is MemberExpression)
{
me = expression as MemberExpression;
}
if (expression is LambdaExpression)
{
le = expression as LambdaExpression;
if (le.Body is MemberExpression)
{
me = le.Body as MemberExpression;
}
else if (le.Body is UnaryExpression)
{
me = (le.Body as UnaryExpression).Operand as MemberExpression;
}
else if(le.Body is MethodCallExpression mexp && mexp.Method.Name == "get_Item")
{
object index = 0;
me = mexp.Object as MemberExpression;
}
}
string rv = "";
if (me != null)
{
rv = me.Member.Name;
}
while (me != null && getAll && me.NodeType == ExpressionType.MemberAccess)
{
Expression exp = me.Expression;
if (exp is MemberExpression)
{
rv = (exp as MemberExpression).Member.Name + "." + rv;
me = exp as MemberExpression;
}
else if (exp is MethodCallExpression)
{
var mexp = exp as MethodCallExpression;
if (mexp.Method.Name == "get_Item")
{
object index = 0;
if (mexp.Arguments[0] is MemberExpression)
{
var obj = ((mexp.Arguments[0] as MemberExpression).Expression as ConstantExpression).Value;
index = obj.GetType().GetField((mexp.Arguments[0] as MemberExpression).Member.Name).GetValue(obj);
}
else
{
index = (mexp.Arguments[0] as ConstantExpression).Value;
}
rv = (mexp.Object as MemberExpression).Member.Name + "[" + index + "]." + rv;
me = mexp.Object as MemberExpression;
}
}
else
{
break;
}
}
return rv;
}
public static Expression GetMemberExp(this ParameterExpression self, Expression member)
{
return self.GetMemberExp(member.GetPropertyName());
}
public static Expression GetMemberExp(this ParameterExpression self, string memberName)
{
var names = memberName.Split(',');
Expression rv = Expression.PropertyOrField(self, names[0]); ;
for (int i = 1; i < names.Length; i++)
{
rv = Expression.PropertyOrField(rv, names[i]);
}
return rv;
}
///
/// 获取属性名的Id形式,将属性名中的.转换为_,适合作为HTML中的Id使用
///
/// 属性表达式
/// 是否获取全部级别名称,比如a.b.c
/// 属性Id
public static string GetPropertyId(this Expression expression, bool getAll = true)
{
return GetPropertyName(expression, getAll).GetIdByName();
}
///
/// 获取正则表达式错误
///
/// 属性信息
/// 错误文本
public static string GetRegexErrorMessage(this MemberInfo pi)
{
string rv = "";
if (pi.GetCustomAttributes(typeof(RegularExpressionAttribute), false).FirstOrDefault() is RegularExpressionAttribute dis && !string.IsNullOrEmpty(dis.ErrorMessage))
{
rv = dis.ErrorMessage;
if (CoreProgram._localizer != null)
{
rv = CoreProgram._localizer[rv];
}
}
else
{
rv = "";
}
return rv;
}
///
/// 获取属性显示名称
///
/// 属性信息
///
/// 属性名称
public static string GetPropertyDisplayName(this MemberInfo pi, IStringLocalizer local = null)
{
string rv = "";
if (pi.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault() is DisplayAttribute dis && !string.IsNullOrEmpty(dis.Name))
{
rv = dis.Name;
if (local == null)
{
if (CoreProgram._localizer != null)
{
rv = CoreProgram._localizer[rv];
}
}
else
{
rv = local[rv];
}
}
else
{
rv = pi.Name;
}
return rv;
}
///
/// 获取属性显示名称
///
/// 属性表达式
///
/// 属性显示名称
public static string GetPropertyDisplayName(this Expression expression, IStringLocalizer local = null)
{
return GetPropertyDisplayName(expression.GetPropertyInfo(), local);
}
///
/// 获取枚举显示名称
///
/// 枚举值
/// 枚举显示名称
public static string GetEnumDisplayName(this Enum value)
{
return GetEnumDisplayName(value.GetType(), value.ToString());
}
///
/// 获取属性信息
///
/// 属性表达式
/// 属性信息
public static PropertyInfo GetPropertyInfo(this Expression expression)
{
MemberExpression me = null;
LambdaExpression le = null;
if (expression is MemberExpression)
{
me = expression as MemberExpression;
}
if (expression is LambdaExpression)
{
le = expression as LambdaExpression;
if (le.Body is MemberExpression)
{
me = le.Body as MemberExpression;
}
if (le.Body is UnaryExpression)
{
me = (le.Body as UnaryExpression).Operand as MemberExpression;
}
}
PropertyInfo rv = null;
if (me != null)
{
rv = me.Member.DeclaringType.GetSingleProperty(me.Member.Name);
}
return rv;
}
///
/// 获取属性值
///
/// 属性表达式
/// 属性所在实例
/// 属性值
public static object GetPropertyValue(this object obj, LambdaExpression exp)
{
//获取表达式的值,并过滤单引号
try
{
var expValue = exp.Compile().DynamicInvoke(obj);
object val = expValue;
return val;
}
catch
{
return "";
}
}
public static object GetPropertyValue(this object obj, string property)
{
//获取表达式的值,并过滤单引号
try
{
return obj.GetType().GetSingleProperty(property).GetValue(obj); ;
}
catch
{
return "";
}
}
public static List GetPropertySiblingValues(this object obj, string propertyName)
{
if(obj == null)
{
return new List();
}
Regex reg = new Regex("(.*?)\\[\\-?\\d?\\]\\.(.*?)$");
var match = reg.Match(propertyName);
if (match.Success)
{
var name1 = match.Groups[1].Value;
var name2 = match.Groups[2].Value;
var levels = name1.Split('.');
var objtype = obj.GetType();
var pe = Expression.Parameter(objtype);
var member = Expression.Property(pe, objtype.GetSingleProperty(levels[0]));
for (int i = 1; i < levels.Length; i++)
{
member = Expression.Property(member, member.Type.GetSingleProperty(levels[i]));
}
var pe2 = Expression.Parameter(member.Type.GetGenericArguments()[0]);
var cast = Expression.Call(typeof(Enumerable), "Cast", new Type[] { pe2.Type }, member);
var name2exp = Expression.Property(pe2, pe2.Type.GetSingleProperty(name2));
var selectexp = Expression.Call(name2exp, "ToString", Type.EmptyTypes);
Expression select = Expression.Call(
typeof(Enumerable),
"Select",
new Type[] { pe2.Type, typeof(string) },
cast,
Expression.Lambda(selectexp, pe2));
var lambda = Expression.Lambda(select, pe);
var rv = new List();
try
{
rv = (lambda.Compile().DynamicInvoke(obj) as IEnumerable)?.ToList();
}
catch { }
return rv;
}
else
{
return new List();
}
}
///
/// 判断属性是否必填
///
/// 属性信息
/// 是否必填
public static bool IsPropertyRequired(this MemberInfo pi)
{
bool isRequired = false;
if (pi != null)
{
//如果需要显示星号,则判断是否是必填项,如果是必填则在内容后面加上星号
//所有int,float。。。这种Primitive类型的,肯定都是必填
Type t = pi.GetMemberType();
if (t != null && (t.IsPrimitive() || t.IsEnum() || t == typeof(decimal) || t == typeof(Guid)))
{
isRequired = true;
}
else
{
//对于其他类,检查是否有RequiredAttribute,如果有就是必填
if (pi.GetCustomAttributes(typeof(RequiredAttribute), false).FirstOrDefault() is RequiredAttribute required && required.AllowEmptyStrings == false)
{
isRequired = true;
}
else if (pi.GetCustomAttributes(typeof(KeyAttribute), false).FirstOrDefault() != null)
{
isRequired = true;
}
}
}
return isRequired;
}
///
/// 设置属性值
///
/// 属性所在实例
/// 属性名
/// 要赋的值
/// 属性前缀
/// 是否为字符串格式的值
public static void SetPropertyValue(this object source, string property, object value, string prefix = null, bool stringBasedValue = false)
{
try
{
property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty);
List level = new List();
if (property.Contains('.'))
{
level.AddRange(property.Split('.'));
}
else
{
level.Add(property);
}
if (!string.IsNullOrWhiteSpace(prefix))
{
level.Insert(0, prefix);
}
object temp = source;
Type tempType = source.GetType();
for (int i = 0; i < level.Count - 1; i++)
{
var member = tempType.GetMember(level[i])[0];
if (member != null)
{
var va = member.GetMemberValue(temp);
if (va != null)
{
temp = va;
}
else
{
var newInstance = member.GetMemberType().GetConstructor(Type.EmptyTypes).Invoke(null);
member.SetMemberValue(temp, newInstance, null);
temp = newInstance;
}
tempType = member.GetMemberType();
}
}
var memberInfos = tempType.GetMember(level.Last());
if (!memberInfos.Any())
{
return;
}
var fproperty = memberInfos[0];
if (value == null || ((value is StringValues s) && StringValues.IsNullOrEmpty(s)))
{
fproperty.SetMemberValue(temp, null, null);
return;
}
bool isArray = false;
if (value != null && value.GetType().IsArray == true)
{
isArray = true;
}
if (stringBasedValue == true)
{
Type propertyType = fproperty.GetMemberType();
if (propertyType.IsGeneric(typeof(List<>)) == true)
{
var list = propertyType.GetConstructor(Type.EmptyTypes).Invoke(null) as IList;
var gs = propertyType.GenericTypeArguments;
try
{
if (value.GetType() == typeof(StringValues))
{
var strVals = (StringValues)value;
var a = strVals.ToArray();
for (int i = 0; i < a.Length; i++)
{
list.Add(a[i].ConvertValue(gs[0]));
}
}
else if (isArray)
{
var a = (value as object[]);
for (int i = 0; i < a.Length; i++)
{
list.Add(a[i].ConvertValue(gs[0]));
}
}
else
{
list = value.ConvertValue(propertyType) as IList;
}
}
catch { }
fproperty.SetMemberValue(temp, list, null);
}
else if (propertyType.IsArray)
{
try
{
var strVals = (StringValues)value;
var eletype = propertyType.GetElementType();
var arr = Array.CreateInstance(eletype, strVals.Count);
for (int i = 0; i < arr.Length; i++)
{
arr.SetValue(strVals[i].ConvertValue(eletype), i);
}
fproperty.SetMemberValue(temp, arr, null);
}
catch { }
}
else
{
if (isArray)
{
var a = (value as object[]);
if (a.Length == 1)
{
value = a[0];
}
}
if (value is string)
{
value = value.ToString().Replace("\\", "/");
}
fproperty.SetMemberValue(temp, value, null);
}
}
else
{
if (value is string)
{
value = value.ToString().Replace("\\", "/");
}
fproperty.SetMemberValue(temp, value, null);
}
}
catch
{
}
}
///
/// 根据MemberInfo获取值
///
/// MemberInfo
/// 所在实例
/// 如果是数组,指定数组下标。默认为null
/// MemberInfo的值
public static object GetMemberValue(this MemberInfo mi, object obj, object[] index = null)
{
object rv = null;
if (mi.MemberType == MemberTypes.Property)
{
rv = ((PropertyInfo)mi).GetValue(obj, index);
}
else if (mi.MemberType == MemberTypes.Field)
{
rv = ((FieldInfo)mi).GetValue(obj);
}
return rv;
}
///
/// 设定MemberInfo的值
///
/// MemberInfo
/// 所在实例
/// 要赋的值
/// 如果是数组,指定数组下标。默认为null
public static void SetMemberValue(this MemberInfo mi, object obj, object val, object[] index = null)
{
object newval = val;
if (val is string s)
{
if (string.IsNullOrEmpty(s))
{
val = null;
}
}
if (val != null && val.GetType() != mi.GetMemberType())
{
newval = val.ConvertValue(mi.GetMemberType());
}
if (mi.MemberType == MemberTypes.Property)
{
((PropertyInfo)mi).SetValue(obj, newval, index);
}
else if (mi.MemberType == MemberTypes.Field)
{
((FieldInfo)mi).SetValue(obj, newval);
}
}
///
/// 获取某个MemberInfo的类型
///
/// MemberInfo
/// 类型
public static Type GetMemberType(this MemberInfo mi)
{
Type rv = null;
if (mi != null)
{
if (mi.MemberType == MemberTypes.Property)
{
rv = ((PropertyInfo)mi).PropertyType;
}
else if (mi.MemberType == MemberTypes.Field)
{
rv = ((FieldInfo)mi).FieldType;
}
}
return rv;
}
///
/// 获取枚举显示名称
///
/// 枚举类型
/// 枚举值
/// 枚举显示名称
public static string GetEnumDisplayName(Type enumType, string value)
{
string rv = "";
FieldInfo field = null;
if (enumType.IsEnum())
{
field = enumType.GetField(value);
}
//如果是nullable的枚举
if (enumType.IsGeneric(typeof(Nullable<>)) && enumType.GetGenericArguments()[0].IsEnum())
{
field = enumType.GenericTypeArguments[0].GetField(value);
}
if (field != null)
{
var attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true).ToList();
if (attribs.Count > 0)
{
rv = ((DisplayAttribute)attribs[0]).GetName();
if (CoreProgram._localizer != null)
{
rv = CoreProgram._localizer[rv];
}
}
else
{
rv = value;
}
}
return rv;
}
public static string GetEnumDisplayName(Type enumType, int value)
{
string rv = "";
FieldInfo field = null;
string ename = "";
if (enumType.IsEnum())
{
ename = enumType.GetEnumName(value);
field = enumType.GetField(ename);
}
//如果是nullable的枚举
if (enumType.IsGeneric(typeof(Nullable<>)) && enumType.GetGenericArguments()[0].IsEnum())
{
ename = enumType.GenericTypeArguments[0].GetEnumName(value);
field = enumType.GenericTypeArguments[0].GetField(ename);
}
if (field != null)
{
var attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true).ToList();
if (attribs.Count > 0)
{
rv = ((DisplayAttribute)attribs[0]).GetName();
if (CoreProgram._localizer != null)
{
rv = CoreProgram._localizer[rv];
}
}
else
{
rv = ename;
}
}
return rv;
}
///
/// 转化值
///
/// 要转换的值
/// 转换后的类型
/// 转换后的值
public static object ConvertValue(this object value, Type propertyType)
{
object val = null;
if (propertyType.IsGeneric(typeof(Nullable<>)) == true)
{
var gs = propertyType.GenericTypeArguments;
try
{
val = ConvertValue(value, gs[0]);
}
catch { }
}
else if (propertyType.IsEnum())
{
val = Enum.Parse(propertyType, value.ToString());
}
else if (propertyType == typeof(string))
{
val = value?.ToString().Trim();
}
else if (propertyType == typeof(Guid))
{
bool suc = Guid.TryParse(value?.ToString(), out Guid g);
if (suc)
{
val = g;
}
else
{
val = Guid.Empty;
}
}
else if (propertyType == typeof(DateRange))
{
if (DateRange.TryParse(value.ToString(), out var result))
{
val = result;
}
else
{
val = DateRange.Default;
}
}
else
{
try
{
if (value.ToString().StartsWith("`") && value.ToString().EndsWith("`"))
{
string inner = value.ToString().Trim('`').TrimEnd(',');
if (!string.IsNullOrWhiteSpace(inner))
{
val = propertyType.GetConstructor(Type.EmptyTypes).Invoke(null);
string[] pair = inner.Split(',');
var gs = propertyType.GetGenericArguments();
foreach (var p in pair)
{
(val as IList).Add(Convert.ChangeType(p, gs[0]));
}
}
}
else
{
val = Convert.ChangeType(value.ToString(), propertyType);
}
}
catch
{
}
}
return val;
}
public static object MakeList(Type innerType, string propertyName, object[] values)
{
object rv = typeof(List<>).MakeGenericType(innerType).GetConstructor(Type.EmptyTypes).Invoke(null);
var mi = rv.GetType().GetMethod("Add");
var con = innerType.GetConstructor(Type.EmptyTypes);
foreach (var item in values)
{
var newobj = con.Invoke(null);
newobj.SetPropertyValue(propertyName, item);
mi.Invoke(rv, new object[] { newobj });
}
return rv;
}
}
}