zoukankan      html  css  js  c++  java
  • 泛型妥托优化反射

    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);
  • 相关阅读:
    WinCE 测试网速
    YII 关联表查询
    YII CMenu配置
    php扩展开发笔记1
    使用Mysql EXPLAIN分析、优化SQL语句
    使用Mysql EXPLAIN分析、优化SQL语句 (续)
    jquery提交中文导致乱码
    *nix 命令记(持续更新)
    php 函数中使用static
    xmlhttprequest获取TransferEncoding:chunked分时编码输出
  • 原文地址:https://www.cnblogs.com/zhshlimi/p/5504680.html
Copyright © 2011-2022 走看看