You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
6.8 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Utils.Refelector
{
public class ReflectionUtil
{
public static TResult GetPrivateField<TClass, TResult>(TClass obj, string field)
{
Type type = obj.GetType();
var privateField = type.GetField(field, BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.ExactBinding);
return (TResult)privateField.GetValue(obj);
}
/// <summary>
/// 执行静态非公有方法。
/// <para>当方法有重载时,该方法报错,需要使用指定了参数类型的那个方法</para>
/// <para>即:ExecuteStaticFunc(Type type, string func, Type[] types, params object[] parameters)</para>
/// </summary>
/// <param name="type">方法所在类的类型</param>
/// <param name="func">方法名</param>
/// <param name="parameters">参数</param>
public static object ExecuteNotPublicStaticFunc(Type type, string func, params object[] parameters)
{
return type.GetMethod(func, BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Static).Invoke(null, parameters);
}
/// <summary>
/// 执行静态非公有方法
/// </summary>
/// <param name="type">方法所在类的类型</param>
/// <param name="func">方法名</param>
/// <param name="types">方法的参数的类型,其顺序为方法的参数的顺序</param>
/// <param name="parameters">参数</param>
public static object ExecuteNotPublicStaticFunc(Type type, string func, Type[] types, params object[] parameters)
{
if (types.Length != parameters.Length)
throw new ArgumentException("第三个参数和后面的参数的个数不匹配");
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
return GetMethod(methods, types).Invoke(null, parameters);
}
/// <summary>
/// 从指定的方法数组中,找出方法的参数的Type为指定Type的方法。
/// <para>即:找出参数类型的Type的个数与顺序符合本方法第二个参数的方法。</para>
/// <para>没找到则返回null</para>
/// </summary>
public static MethodInfo GetMethod(MethodInfo[] methods, Type[] types)
{
foreach (var item in methods) {
var param = item.GetParameters();
if (param.Length != types.Length)
continue;
bool tatolSame = true;
for (int i = 0; i < types.Length; i++) {
if (types[i] != param[i].ParameterType) {
tatolSame = false;
break;
}
}
if (tatolSame)
return item;
}
return null;
}
//public static PropertyInfo[] GetField<TClass>(TClass obj)
//{
// var type = obj.GetType();
// return type.GetProperties();
//}
//public static void SetValue<TClass>(TClass obj)
//{
// var properties = GetField(obj);
// properties[0].SetValue(obj, "", null);
//}
/// <summary>
/// 获取公共属性的值。
/// <para>忽略索引。如:public char this[int index] { get; }</para>
/// <para>忽略不可读的属性</para>
/// </summary>
public static Dictionary<string, object> GetPublicPropertyValues<TClass>(TClass obj)
{
Dictionary<string, object> result = new Dictionary<string, object>();
if (obj == null)
return result;
var properties = obj.GetType().GetProperties();
foreach (var field in properties) {
if (field.GetIndexParameters().Length > 0)//如果是索引,则忽略。索引:public char this[int index] { get; }
continue;
if (!field.CanRead)
continue;
result.Add(field.Name, field.GetValue(obj, null));
}
return result;
}
/// <summary>
/// 设置指定对象的值为values
/// <para>忽略索引。如:public char this[int index] { get; }</para>
/// <para>忽略不可写的属性</para>
/// </summary>
public static void SetValues<TClass, TValue>(TClass obj, Dictionary<string, TValue> values)
{
if (obj == null)
return;
if (values == null || values.Count == 0)
return;
var dmoType = obj.GetType();
var properties = dmoType.GetProperties();
foreach (var field in properties) {
if (field.GetIndexParameters().Length > 0)//如果是索引,则忽略。索引:public char this[int index] { get; }
continue;
if (!field.CanWrite)
continue;
var propertyType = dmoType.GetProperty(field.Name).PropertyType;
if (values.Keys.Contains(field.Name)) {
object value = values[field.Name];
if (value == null || !propertyType.Equals(value.GetType())) {
value = ChangeType(propertyType, value);
}
dmoType.GetProperty(field.Name).SetValue(obj, value, null);
}
}
}
private static object ChangeType(Type propertyType, object value)
{//TODO:这个是为了处理在设置清单的值时,由于给定的值的类型是string类型,导致在设置值时类型不正确。之所以“给定的值的类型是string类型”,是因为在CommanRow类中,获取控件值时返回的类型是string(public string this[string field]的这个)。如果能解决上述问题,则不需要这个方法,引用这个方法的地方,也就可以修改之o
if (propertyType.Equals(typeof(long))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return 0;
return long.Parse(value.ToString());
} else if (propertyType.Equals(typeof(long?))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return null;
return long.Parse(value.ToString());
} else if (propertyType.Equals(typeof(int))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return 0;
return int.Parse(value.ToString());
} else if (propertyType.Equals(typeof(int?))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return null;
return int.Parse(value.ToString());
} else if (propertyType.Equals(typeof(decimal))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return 0;
return decimal.Parse(value.ToString());
} else if (propertyType.Equals(typeof(decimal?))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return null;
return decimal.Parse(value.ToString());
} else if (propertyType.Equals(typeof(bool))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return false;
return bool.Parse(value.ToString());
} else if (propertyType.Equals(typeof(bool?))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return null;
return bool.Parse(value.ToString());
} else if (propertyType.Equals(typeof(DateTime))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return DateTime.Now;//TODO:如何处理?
return bool.Parse(value.ToString());
} else if (propertyType.Equals(typeof(DateTime?))) {
if (value == null || string.IsNullOrEmpty(value.ToString()))
return null;
return DateTime.Parse(value.ToString());
} else
throw new ApplicationException("未处理");
}
}
}