using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using NewLife.Collections;
namespace NewLife.Reflection
{
/// <summary>快速属性访问</summary>
public class PropertyInfoX : MemberInfoX
{
#region 属性
/// <summary>目标属性</summary>
public PropertyInfo Property { get; set; }
private List<String> hasLoad = new List<String>();
FastGetValueHandler _GetHandler;
/// <summary>快速调用委托,延迟到首次使用才创建</summary>
FastGetValueHandler GetHandler
{
get
{
if (_GetHandler == null && Property.CanRead)
{
var mi = Property.GetGetMethod() ?? Property.GetGetMethod(true);
if (mi != null) _GetHandler = GetValueInvoker(mi);
}
return _GetHandler;
}
}
FastSetValueHandler _SetHandler;
/// <summary>快速调用委托,延迟到首次使用才创建</summary>
FastSetValueHandler SetHandler
{
get
{
if (_SetHandler == null && Property.CanWrite)
{
var mi = Property.GetSetMethod() ?? Property.GetSetMethod(true);
if (mi != null) _SetHandler = SetValueInvoker(mi);
}
return _SetHandler;
}
}
#endregion
#region 构造
private PropertyInfoX(PropertyInfo property) : base(property) { Property = property; }
private static DictionaryCache<PropertyInfo, PropertyInfoX> cache = new DictionaryCache<PropertyInfo, PropertyInfoX>();
/// <summary>创建</summary>
/// <param name="property">属性</param>
/// <returns></returns>
public static PropertyInfoX Create(PropertyInfo property)
{
if (property == null) return null;
return cache.GetItem(property, key => new PropertyInfoX(key));
}
/// <summary>创建</summary>
/// <param name="type">类型</param>
/// <param name="name">名称</param>
/// <returns></returns>
public new static PropertyInfoX Create(Type type, String name)
{
// name不判断0长度字符串,因为0长度字符串可以做标识符
if (type == null || name == null) return null;
var property = type.GetProperty(name);
if (property == null) property = type.GetProperty(name, DefaultBinding);
if (property == null) property = type.GetProperty(name, DefaultBinding | BindingFlags.IgnoreCase);
if (property == null)
{
var ps = type.GetProperties();
foreach (var item in ps)
{
if (item.Name.EqualIgnoreCase(name))
{
property = item;
break;
}
}
}
if (property == null && type.BaseType != null && type.BaseType != typeof(Object)) return Create(type.BaseType, name);
if (property == null) return null;
return Create(property);
}
#endregion
#region 创建动态方法
delegate Object FastGetValueHandler(Object obj);
delegate void FastSetValueHandler(Object obj, Object value);
private static FastGetValueHandler GetValueInvoker(MethodInfo method)
{
//定义一个没有名字的动态方法
var dynamicMethod = new DynamicMethod(String.Empty, typeof(Object), new Type[] { typeof(Object) }, method.DeclaringType.Module, true);
var il = dynamicMethod.GetILGenerator();
//if (!method.IsStatic) il.Emit(OpCodes.Ldarg_0);
if (!method.IsStatic) il.Ldarg(0).CastFromObject(method.DeclaringType);
// 目标方法没有参数
il.Call(method)
.BoxIfValueType(method.ReturnType)
.Ret();
return (FastGetValueHandler)dynamicMethod.CreateDelegate(typeof(FastGetValueHandler));
}
private static FastSetValueHandler SetValueInvoker(MethodInfo method)
{
//定义一个没有名字的动态方法
var dynamicMethod = new DynamicMethod(String.Empty, null, new Type[] { typeof(Object), typeof(Object) }, method.DeclaringType.Module, true);
var il = dynamicMethod.GetILGenerator();
//if (!method.IsStatic) il.Emit(OpCodes.Ldarg_0);
if (!method.IsStatic) il.Ldarg(0).CastFromObject(method.DeclaringType);
// 目标方法只有一个参数
il.Ldarg(1)
.CastFromObject(method.GetParameters()[0].ParameterType)
.Call(method)
.Ret();
return (FastSetValueHandler)dynamicMethod.CreateDelegate(typeof(FastSetValueHandler));
}
#endregion
#region 调用
/// <summary>取值</summary>
/// <param name="obj"></param>
/// <returns></returns>
[DebuggerHidden]
[DebuggerStepThrough]
public override Object GetValue(Object obj)
{
if (GetHandler == null) throw new InvalidOperationException("{0}不支持GetValue操作!".F(this));
return GetHandler.Invoke(obj);
}
// 快速委托没有什么性能优势,Emit已经足够快
//public Object GetValue2(Object obj)
//{
// var fg = FastGet;
// if (fg != null) return fg.Invoke(obj);
// if (GetHandler == null) throw new InvalidOperationException("不支持GetValue操作!");
// return GetHandler.Invoke(obj);
//}
/// <summary>赋值</summary>
/// <param name="obj"></param>
/// <param name="value">数值</param>
[DebuggerHidden]
[DebuggerStepThrough]
public override void SetValue(Object obj, Object value)
{
if (SetHandler == null) throw new InvalidOperationException("{0}不支持SetValue操作!".F(this));
// 如果类型不匹配,先做类型转换
if (value != null && !Type.IsAssignableFrom(value.GetType())) value = TypeX.ChangeType(value, Type);
SetHandler.Invoke(obj, value);
}
/// <summary>快速获取静态属性。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <param name="type">类型</param>
/// <param name="target">目标对象</param>
/// <param name="name">名称</param>
/// <returns></returns>
internal static Object GetValue(Type type, Object target, String name)
{
if (type == null && target != null) type = target.GetType();
if (type == null) throw new ArgumentNullException("type");
if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
PropertyInfoX pix = Create(type, name);
if (pix == null) throw new XException("类{0}中无法找到{1}属性!", type.Name, name);
return pix.GetValue(target);
}
/// <summary>静态快速赋值。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <param name="type">类型</param>
/// <param name="target">目标对象</param>
/// <param name="name">名称</param>
/// <param name="value">数值</param>
internal static void SetValue(Type type, Object target, String name, Object value)
{
if (type == null && target != null) type = target.GetType();
if (type == null) throw new ArgumentNullException("type");
if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
PropertyInfoX pix = Create(type, name);
if (pix == null) throw new XException("类{0}中无法找到{1}属性!", type.Name, name);
pix.SetValue(target, value);
}
/// <summary>快速获取静态属性。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <param name="type">类型</param>
/// <param name="name">名称</param>
/// <returns></returns>
public static Object GetValue(Type type, String name) { return GetValue(type, null, name); }
/// <summary>静态属性快速赋值。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <param name="type">类型</param>
/// <param name="name">名称</param>
/// <param name="value">数值</param>
public static void SetValue(Type type, String name, Object value) { SetValue(type, null, name, value); }
/// <summary>静态快速取值。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="target">目标对象</param>
/// <param name="name">名称</param>
/// <returns></returns>
public static TResult GetValue<TResult>(Object target, String name)
{
//if (target == null || String.IsNullOrEmpty(name)) return default(TResult);
if (target == null) throw new ArgumentNullException("target");
if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
return (TResult)GetValue(target.GetType(), target, name);
}
/// <summary>快速获取静态属性。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <typeparam name="TTarget"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="name">名称</param>
/// <returns></returns>
public static TResult GetValue<TTarget, TResult>(String name) { return (TResult)GetValue(typeof(TTarget), null, name); }
/// <summary>成员属性快速赋值。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <param name="target">目标对象</param>
/// <param name="name">名称</param>
/// <param name="value">数值</param>
public static void SetValue(Object target, String name, Object value) { SetValue(target.GetType(), target, name, value); }
/// <summary>快速设置静态属性。若属性不存在,会抛出异常。不确定属性是否存在时,建议使用Create方法</summary>
/// <typeparam name="TTarget"></typeparam>
/// <param name="name">名称</param>
/// <param name="value">数值</param>
public static void SetValue<TTarget>(String name, Object value) { SetValue(typeof(TTarget), null, name, value); }
#endregion
#region 类型转换
/// <summary>类型转换</summary>
/// <param name="obj"></param>
/// <returns></returns>
public static implicit operator PropertyInfo(PropertyInfoX obj)
{
return obj != null ? obj.Property : null;
}
/// <summary>类型转换</summary>
/// <param name="obj"></param>
/// <returns></returns>
public static implicit operator PropertyInfoX(PropertyInfo obj)
{
return obj != null ? Create(obj) : null;
}
#endregion
#region 快速委托调用
// 快速委托没有什么性能优势,Emit已经足够快
//private Boolean initFastGet;
//private FastMethod _FastGet;
///// <summary>快速获取</summary>
//FastMethod FastGet
//{
// get
// {
// if (!initFastGet)
// {
// var fm = new FastMethod(GetMethod);
// if (fm.Supported) _FastGet = fm;
// initFastGet = true;
// }
// return _FastGet;
// }
//}
#endregion
#region 重载
/// <summary>已重载。</summary>
/// <returns></returns>
public override string ToString()
{
return (Property.DeclaringType != null ? Property.DeclaringType.Name : null) + "." + (Property != null ? Property.Name : null);
}
#endregion
}
}
|