using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using cylsg.utility.Extend;
using Microsoft.Extensions.Primitives;
namespace cylsg.utility.Extend
{
///
/// 反射扩展函数
///
public static class TypeAndExpressionEx
{
#region 属性扩展 反射
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);
#pragma warning disable 8604
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;
}
if (le.Body is UnaryExpression)
{
me = (le.Body as UnaryExpression).Operand 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;
}
///
/// 获取正则表达式错误
///
/// 属性信息
/// 错误文本
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)
{
string rv = "";
if (pi.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault() is DisplayAttribute dis && !string.IsNullOrEmpty(dis.Name))
{
rv = dis.Name;
}
else
{
rv = pi.Name;
}
return rv;
}
///
/// 获取属性显示名称
///
/// 属性表达式
/// 属性显示名称
public static string GetPropertyDisplayName(this Expression expression)
{
return expression.GetPropertyInfo().GetPropertyDisplayName();
}
///
/// 获取属性的 Description 标注名,如果没有,则返回 属性名称
///
///
///
public static string GetPropertyDescription(this MemberInfo pi)
{
string rv = "";
if (pi.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() is DescriptionAttribute dis && !string.IsNullOrEmpty(dis.Description))
{
rv = dis.Description;
}
else
{
rv = pi.Name;
}
return rv;
}
///
/// 获取属性的 Description 标注名,如果没有,则返回 属性名称
///
///
///
public static string GetPropertyDescription(this Expression expression)
{
return expression.GetPropertyInfo().GetPropertyDisplayName();
}
///
/// 获取枚举显示名称
///
/// 枚举值
/// 枚举显示名称
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 null;
}
}
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();
if (eletype != null)
{
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 = value.ConvertValue(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
{
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;
}
///
/// 获取 是否定义该标签属性
///
///
///
///
public static T? GetAttribute(this MemberInfo pi) where T : Attribute
{
string rv = "";
if (pi.GetCustomAttributes(typeof(T), false).FirstOrDefault() is T dis)
{
return dis;
}
else
{
return null;
}
}
public static ImmutableDictionary> _propertyCache { get; set; } =
new Dictionary>().ToImmutableDictionary();
///
/// 判断是否是泛型
///
/// Type类
/// 泛型类型
/// 判断结果
public static bool IsGeneric(this Type self, Type innerType)
{
if (self.GetTypeInfo().IsGenericType && self.GetGenericTypeDefinition() == innerType)
{
return true;
}
else
{
return false;
}
}
///
/// 判断是否为Nullable<>类型
///
/// Type类
/// 判断结果
public static bool IsNullable(this Type self)
{
return self.IsGeneric(typeof(Nullable<>));
}
///
/// 判断是否为List<>类型
///
/// Type类
/// 判断结果
public static bool IsList(this Type self)
{
return self.IsGeneric(typeof(List<>)) || self.IsGeneric(typeof(IEnumerable<>));
}
///
/// 判断是否为List<>类型
///
/// Type类
/// 判断结果
public static bool IsListOf(this Type self)
{
if (self.IsGeneric(typeof(List<>)) && typeof(T).IsAssignableFrom(self.GenericTypeArguments[0]))
{
return true;
}
else
{
return false;
}
}
#region 判断是否为枚举
///
/// 判断是否为枚举
///
/// Type类
/// 判断结果
public static bool IsEnum(this Type self)
{
return self.GetTypeInfo().IsEnum;
}
///
/// 判断是否为枚举或者可空枚举
///
///
///
public static bool IsEnumOrNullableEnum(this Type self)
{
if (self == null)
{
return false;
}
if (self.IsEnum)
{
return true;
}
else
{
if (self.IsGenericType && self.GetGenericTypeDefinition() == typeof(Nullable<>) && self.GetGenericArguments()[0].IsEnum)
{
return true;
}
else
{
return false;
}
}
}
#endregion
///
/// 判断是否为值类型 基础值类型
///
/// Type类
/// 判断结果
public static bool IsPrimitive(this Type self)
{
return self.GetTypeInfo().IsPrimitive || self == typeof(decimal);
}
///
/// 判断值是否是数字基础类型
///
///
///
public static bool IsNumber(this Type self)
{
Type checktype = self;
if (self.IsNullable())
{
checktype = self.GetGenericArguments()[0];
}
if (checktype == typeof(int) || checktype == typeof(short) || checktype == typeof(long) || checktype == typeof(float) || checktype == typeof(decimal) || checktype == typeof(double))
{
return true;
}
else
{
return false;
}
}
#region 判断是否是Bool
///
/// 是否是bool类型
///
///
///
public static bool IsBool(this Type self)
{
return self == typeof(bool);
}
///
/// 判断是否是 bool or bool?类型
///
///
///
public static bool IsBoolOrNullableBool(this Type self)
{
if (self == null)
{
return false;
}
if (self == typeof(bool) || self == typeof(bool?))
{
return true;
}
else
{
return false;
}
}
#endregion
///
/// 根据名字获取
///
///
///
///
public static PropertyInfo? GetSingleProperty(this Type self, string name)
{
if (self.FullName == null)
throw new Exception("属性名为空");
if (_propertyCache.ContainsKey(self.FullName) == false)
{
var properties = self.GetProperties().ToList();
_propertyCache = _propertyCache.Add(self.FullName, properties);
return properties.Where(x => x.Name == name).FirstOrDefault();
}
else
{
return _propertyCache[self.FullName].Where(x => x.Name == name).FirstOrDefault();
}
}
///
/// 获取属性列表 并将 列表属性放入缓存
///
///
///
public static PropertyInfo? GetSingleProperty(this Type self, Func where)
{
if (self.FullName == null)
throw new Exception("属性名为空");
if (_propertyCache.ContainsKey(self.FullName) == false)
{
var properties = self.GetProperties().ToList();
_propertyCache = _propertyCache.Add(self.FullName, properties);
return properties.Where(where).FirstOrDefault();
}
else
{
return _propertyCache[self.FullName].Where(where).FirstOrDefault();
}
}
///
/// 获取属性列表 并将 列表属性放入缓存
///
///
///
public static List GetAllProperties(this Type self)
{
if (self.FullName == null)
throw new Exception("属性名为空");
if (_propertyCache.ContainsKey(self.FullName) == false)
{
var properties = self.GetProperties().ToList();
_propertyCache = _propertyCache.Add(self.FullName, properties);
return properties;
}
else
{
return _propertyCache[self.FullName];
}
}
#endregion
}
}