泛型妥托优化反射

 

public class Order
{
public string OrderId { get; set; }
}
public class SetterWrapper<TTarget, TValue>
{
private Action<TTarget, TValue> _setter;
public SetterWrapper(PropertyInfo propInfo)
{
if (propInfo == null)
throw new ArgumentNullException("propertyInfo");
if (!propInfo.CanWrite)
throw new NotSupportedException("属性是只读或Private Setter");
MethodInfo setMethod = propInfo.GetSetMethod(true);
_setter = (Action<TTarget, TValue>)Delegate.CreateDelegate(typeof(Action<TTarget, TValue>), null, setMethod);
}
public void SetValue(TTarget target, TValue val)
{
if (_setter != null)
{
_setter(target, val);
}
}
}
public class GetterWrapper<TTarget, TValue>
{
private Func<TTarget, TValue> _getter;
public GetterWrapper(PropertyInfo propInfo)
{
if (propInfo == null)
throw new ArgumentNullException("propertyInfo");
if (!propInfo.CanRead)
throw new NotSupportedException("属性是不可读或Private Getter");
MethodInfo getMethod = propInfo.GetGetMethod();
_getter = (Func<TTarget, TValue>)Delegate.CreateDelegate(typeof(Func<TTarget, TValue>), null, getMethod);
}
public TValue GetValue(TTarget target)
{
if (_getter != null)
{
return _getter(target);
}
return default(TValue);
}
}

 

static void Main(string[] args)
{
Order order=new Order(){OrderId = "W1234566"};
PropertyInfo piInfo = typeof(Order).GetProperty("OrderId");
int maxCount = 1000*1000;
string v = string.Empty;
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
for (int i = 0; i < maxCount; i++)
{
order.OrderId = i.ToString();
v = order.OrderId;
}
sw.Stop();
Console.WriteLine("直接访问:{0}", sw.ElapsedTicks);

sw.Reset();
sw.Start();

for (int i = 0; i < maxCount; i++)
{
piInfo.SetValue(order,i.ToString());
v = piInfo.GetValue(order).ToString();
}
sw.Stop();
Console.WriteLine("直接反射:{0}", sw.ElapsedTicks);


sw.Reset();
sw.Start();
GetterWrapper<Order, string> getter = new GetterWrapper<Order, string>(piInfo);

SetterWrapper<Order, string> setter = new SetterWrapper<Order, string>(piInfo);
for (int i = 0; i < maxCount; i++)
{

setter.SetValue(order, i.ToString());
v = getter.GetValue(order);
}
sw.Stop();
Console.WriteLine("泛型妥托反射:{0}", sw.ElapsedTicks);
Console.Read();

}

 

 

//win7,vs 2013,8G内存,i5Cpu下测试

 

 

Emit反射

public class PropertyHelper
    {
        /// <summary>
        /// Emit获取属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static Func<T, object> EmitGetter<T>(string propertyName)
        {
            var type = typeof(T);
            var property = type.GetProperty(propertyName);

            var dynamicMethod = new DynamicMethod("get_" + propertyName, typeof(object), new[] { type }, type);
            var iLGenerator = dynamicMethod.GetILGenerator();

            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Callvirt, property.GetGetMethod());
            if (property.PropertyType.IsValueType)
            {
                //// 如果是值类型,装箱
                iLGenerator.Emit(OpCodes.Box, property.PropertyType);
            }
            else
            {
                //// 如果是引用类型,转换
                iLGenerator.Emit(OpCodes.Castclass, property.PropertyType);
            }
            iLGenerator.Emit(OpCodes.Ret);

            return dynamicMethod.CreateDelegate(typeof(Func<T, object>)) as Func<T, object>;
        }

        /// <summary>
        /// Emit属性值赋值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static Action<T, object> EmitSetter<T>(string propertyName)
        {
            var type = typeof(T);
            var callMethod = type.GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);

            //// 获取参数
            var parameterInfo = callMethod.GetParameters()[0];

            var dynamicMethod = new DynamicMethod("EmitCallable", null, new Type[] { type, typeof(object) }, type.Module);
            var iLGenerator = dynamicMethod.GetILGenerator();

            //// 创建一个本地变量,主要用于 Object Type to Propety Type
            var local = iLGenerator.DeclareLocal(parameterInfo.ParameterType, true);

            //// 加载第 2 个参数【(T owner, object value)】的 value
            iLGenerator.Emit(OpCodes.Ldarg_1);
            if (parameterInfo.ParameterType.IsValueType)
            {
                //// 如果是值类型,拆箱
                iLGenerator.Emit(OpCodes.Unbox_Any, parameterInfo.ParameterType);
            }
            else
            {
                //// 如果是引用类型,转换
                iLGenerator.Emit(OpCodes.Castclass, parameterInfo.ParameterType);
            }

            //// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
            iLGenerator.Emit(OpCodes.Stloc, local);
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Ldloc, local);

            //// 调用函数
            iLGenerator.EmitCall(OpCodes.Callvirt, callMethod, null);
            iLGenerator.Emit(OpCodes.Ret);

            return dynamicMethod.CreateDelegate(typeof(Action<T, object>)) as Action<T, object>;
        }
    }

 

调用方法

var model=new Persion("张三");
var theName=PropertyHelper.EmitGetter<Persion>("Name")(model);

 

posted @ 2016-05-18 11:54  zslm___  阅读(449)  评论(0编辑  收藏  举报