using Rapid.Kernel.Expressions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace Rapid.Kernel.Reflection
{
/***************************************************************************************
**
** File Name(文件名) :
* ReflectionExtension.cs
** Creator(创建人):
* LJZ
** Create Time(创建时间):
* 2020.8.28
** Functional Description (功能描述) :
* 实现反射拓展的静态拓展类。
** Remark(备注):
**
** Copyright(c) Rapid k1ng.LJZ Corporation.All rights reserved.
* ***************************************************************************************/
/// <summary>
/// 实现反射拓展的静态拓展类
/// </summary>
[Description("实现反射拓展的静态拓展类")]
public static partial class ReflectionExtension
{
internal static readonly object ms_AnsycLock = new object();
/// <summary>
/// 默认查找级别标记
/// </summary>
[Description("默认查找级别标记")]
internal static BindingFlags ms_SearchFlagDefault =
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
#region Cast 值强制转换
/// <summary>
/// 值强制转换
/// </summary>
/// <param name="val"></param>
/// <param name="targetType"></param>
/// <returns></returns>
public static object Cast(this object val, Type targetType)
{
if (val?.RegardAs(targetType) == true)
{
return val;
}
var tVal = (val is IConvertible
&& targetType.IsAssignableFrom(TypeConsts.IConvertible))
|| TypeConsts.ValuesTypes.Contains(targetType) ?
Convert.ChangeType(val, targetType) : val;
if (tVal?.RegardAs(targetType) == true)
{
return tVal;
}
if (targetType.IsEnum)
{
tVal = Enum.Parse(targetType, tVal?.ToString());
}
else if (TypeConsts.Strings.Contains(tVal?.GetType()) == true)
{
var members = targetType.GetMember("Parse", ms_SearchFlagDefault);
foreach (var member in members)
{
if (member is MethodInfo methodInfo
&& default !=
methodInfo.GetParameters()?.FirstOrDefault(
x => TypeConsts.Strings.Contains(x.ParameterType))
&& methodInfo?.IsStatic == true)
{
tVal = methodInfo.Invoke(null, new object[] { tVal });
}
}
}
return tVal;
}
/// <summary>
/// 值强制转换
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="val"></param>
/// <returns></returns>
public static object Cast<T>(this object val)
{
var targetType = typeof(T);
if (val?.RegardAs(targetType) == true)
{
return val;
}
var tVal = (val is IConvertible
&& targetType.IsAssignableFrom(TypeConsts.IConvertible))
|| TypeConsts.ValuesTypes.Contains(targetType) ?
Convert.ChangeType(val, targetType) : val;
if (tVal?.RegardAs(targetType) == true)
{
return tVal;
}
if (targetType.IsEnum)
{
return Enum.Parse(targetType, tVal?.ToString());
}
else if (TypeConsts.Strings.Contains(tVal?.GetType()) == true)
{
var members = targetType.GetMember("Parse", ms_SearchFlagDefault);
foreach (var member in members)
{
if (member is MethodInfo methodInfo
&& default !=
methodInfo.GetParameters()?.FirstOrDefault(
x => TypeConsts.Strings.Contains(x.ParameterType))
&& methodInfo?.IsStatic == true)
{
return methodInfo.Invoke(null, new object[] { tVal });
}
}
//var method = members[0];
}
return default(T);
}
#endregion
#region RegardAs 是否可被当作某个类型
/// <summary>
/// 是否可被当作某个类型
/// </summary>
/// <param name="instance"></param>
/// <param name="targetType"></param>
/// <returns></returns>
public static bool RegardAs(this Type instanceType, Type targetType)
{
return default != instanceType
&& (instanceType == targetType
|| true == instanceType?.IsSubclassOf(targetType)
|| true == instanceType?.IsAssignableFrom(targetType)
|| true == targetType?.IsSubclassOf(instanceType)
|| true == targetType?.IsAssignableFrom(instanceType));
}
/// <summary>
/// 是否可被当作某个类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance"></param>
/// <returns></returns>
public static bool RegardAs<T>(this Type instanceType)
{
return RegardAs(instanceType, typeof(T));
}
/// <summary>
/// 是否可被当作某个类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance"></param>
/// <returns></returns>
public static bool RegardAs<T>(this object instance)
{
return RegardAs(instance?.GetType(), typeof(T));
}
/// <summary>
/// 是否可被当作某个类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance"></param>
/// <returns></returns>
public static bool RegardAs(this object instance, Type targetType)
{
return RegardAs(instance?.GetType(), targetType);
}
#endregion
#region SetVariable 设置指定对象的变量值
/// <summary>
/// 设置指定对象的变量值
/// </summary>
/// <param name="instance"></param>
/// <param name="propertyOrfieldName"></param>
/// <returns></returns>
public static Exception SetVariable(this object instance, string propertyOrfieldName, object val)
{
if (default == instance)
{
return new Exception("instance is null");
}
var memberInfo = instance.GetType().GetVariableInfo(propertyOrfieldName);
if (memberInfo is PropertyInfo propertyInfo)
{
propertyInfo.SetValue(propertyInfo.IsStatic() ? null : instance, val.Cast(propertyInfo.PropertyType));
}
else if (memberInfo is FieldInfo fieldInfo)
{
fieldInfo.SetValue(fieldInfo.IsStatic() ? null : instance, val.Cast(fieldInfo.FieldType));
}
else if (instance is ExpandoObject
&& instance is IDictionary<string, object> expandoObj
&& expandoObj.ContainsKey(propertyOrfieldName))
{
expandoObj[propertyOrfieldName] = val;
}
return default;
}
#endregion
#region GetVariable 获取指定对象的变量值
/// <summary>
/// 获取指定对象的变量值
/// </summary>
/// <param name="instance"></param>
/// <param name="propertyOrfieldName"></param>
/// <returns></returns>
public static object GetVariable(this object instance, string propertyOrfieldName)
{
if (default == instance)
{
return default;
}
var memberInfo = instance.GetType().GetVariableInfo(propertyOrfieldName);
if (memberInfo is PropertyInfo propertyInfo)
{
return propertyInfo.GetValue(propertyInfo.IsStatic() ? null : instance);
}
else if (memberInfo is FieldInfo fieldInfo)
{
return fieldInfo.GetValue(instance);
}
else if (instance is ExpandoObject
&& instance is IDictionary<string, object> expandoObj
&& expandoObj.ContainsKey(propertyOrfieldName))
{
return expandoObj[propertyOrfieldName];
}
return default;
}
#endregion
#region GetValueInfo 从指定对象的获取变量信息
internal static Dictionary<string, List<MemberInfo>> TypesMembersDictionary { get; } =
new Dictionary<string, List<MemberInfo>>();
public static List<MemberInfo> GetMembersInfos(this Type instanceType)
{
lock (ms_AnsycLock)
{
if (default == instanceType)
return default;
var keyName = instanceType?.FullName;
if (TypesMembersDictionary?.ContainsKey(keyName) == true)
{
return TypesMembersDictionary[keyName];
}
else
{
var membersInfos = instanceType.GetMembers(ms_SearchFlagDefault)?.ToList();
TypesMembersDictionary.Add(keyName, membersInfos);
return membersInfos;
}
}
}
/// <summary>
/// 从指定对象类型的获取变量信息
/// </summary>
/// <param name="instanceType"></param>
/// <param name="propertyOrfieldName"></param>
/// <returns></returns>
public static List<MemberInfo> GetVariablesInfos(this Type instanceType, string propertyOrfieldName = null, bool isContain = false)
{
lock (ms_AnsycLock)
{
if (default == instanceType)
return default;
var memberInfos = instanceType.GetMembersInfos();
if (!string.IsNullOrWhiteSpace(propertyOrfieldName)
&& isContain)
{
memberInfos = memberInfos.Where(x => x?.Name?.Contains(propertyOrfieldName) == true)?.ToList();
}
else if (!isContain
&& !string.IsNullOrWhiteSpace(propertyOrfieldName))
{
memberInfos = memberInfos.Where(x => x?.Name == propertyOrfieldName)?.ToList();
}
memberInfos = memberInfos.OrderBy(x=>x.MemberType)?.ToList();
return memberInfos;
}
}
/// <summary>
/// 从指定对象类型的获取变量信息
/// </summary>
/// <param name="instance"></param>
/// <param name="propertyOrfieldName"></param>
/// <returns></returns>
public static List<MemberInfo> GetVariablesInfos(this object instance, string propertyOrfieldName = null, bool isContain = false)
{
return instance?.GetType()?.GetVariablesInfos(propertyOrfieldName,isContain);
}
/// <summary>
/// 从指定对象类型的获取变量信息
/// </summary>
/// <param name="instanceType"></param>
/// <param name="propertyOrfieldName"></param>
/// <returns></returns>
public static MemberInfo GetVariableInfo(this Type instanceType, string propertyOrfieldName)
{
if (default == instanceType
|| string.IsNullOrWhiteSpace(propertyOrfieldName))
return default;
if (instanceType.GetProperty(propertyOrfieldName, ms_SearchFlagDefault) is PropertyInfo propertyInfo)
return propertyInfo;
if (instanceType.GetField(propertyOrfieldName, ms_SearchFlagDefault) is FieldInfo fieldInfo)
return fieldInfo;
return default;
}
/// <summary>
/// 从指定对象的获取变量信息
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="expression"></param>
/// <returns></returns>
public static MemberInfo GetVariableInfo<T>(this object obj, Expression<Func<T, object>> expression)
{
return typeof(T)?.GetVariableInfo(expression.GetExpression());
}
#endregion
#region GetMethodInfos GetMethodInfo 获取指定名称的方法信息
#region GetMethodInfos 获取指定名称的方法信息
/// <summary>
/// 获取指定名称
/// 所有方法信息
/// </summary>
/// <param name="instanceType">指定类型</param>
/// <param name="methodName"></param>
/// <returns></returns>
public static List<MethodInfo> GetMethodInfos(this Type instanceType, string methodName)
{
var methods = new List<MethodInfo>();
if (default == instanceType
|| string.IsNullOrWhiteSpace(methodName))
return methods;
foreach (var info in
instanceType?.GetMembersInfos()
?.Where(x => MemberTypes.Method == x.MemberType
&& x.Name == methodName))
{
if (info is MethodInfo methodInfo)
{
methods.Add(methodInfo);
}
}
return methods;
}
/// <summary>
/// 获取指定名称
/// 所有方法信息
/// </summary>
/// <param name="instance"></param>
/// <param name="methodName"></param>
/// <returns></returns>
public static List<MethodInfo> GetMethodInfos(this object instance, string methodName)
{
return GetMethodInfos(instance?.GetType(), methodName);
}
#endregion
#region GetMethodInfo 获取指定名称的方法信息
/// <summary>
/// 获取方法
/// 如果存在多个方法
/// 则直接返回参数最少的一个
/// </summary>
/// <param name="instance"></param>
/// <param name="methodName"></param>
/// <param name="parametersTypes"></param>
/// <returns></returns>
public static MethodInfo GetMethodInfo(this object instance, string methodName, Type[] parametersTypes = default)
{
var methodInfos = instance.GetMethodInfos(methodName)?.OrderBy(
x => x?.GetParameters()?.Count())?.ToList();
if (default == methodInfos)
return default;
if (default == parametersTypes)
return methodInfos.FirstOrDefault();
else
{
foreach (var methodInfo in methodInfos)
{
if (methodInfo.GetParameters() is ParameterInfo[] parameterInfos
&& parameterInfos?.Length == parametersTypes.Length)
{
for (var i = 0; i < parametersTypes.Length; i++)
{
if (parametersTypes[i].RegardAs(parameterInfos[i].ParameterType))
{
if (i == parametersTypes.Length - 1)
return methodInfo;
}
else
break;
}
}
}
return default;
}
}
#endregion
#endregion
}
}