动态string转换类

主要用于反射运行时转换类型

  class ConvertString
    {
        private static Dictionary<Type, DynamicMethodExecutor> executorCache = new Dictionary<Type, DynamicMethodExecutor>();
        /// <summary>
        /// Type必须有静态Parse方法供转换调用
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object ToType(string value, Type type)
        {
            if (type == typeof(string)) { return value; }
            DynamicMethodExecutor executor = null;
            if (executorCache.TryGetValue(type, out executor) == false)
            {
                MethodInfo parseMethod = null;
                foreach (MethodInfo mi in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
                {
                    if (mi.Name == "Parse" && mi.GetParameters().Length == 1 && mi.GetParameters()[0].ParameterType == typeof(string))
                    {
                        parseMethod = mi; break;
                    }
                }
                if (parseMethod == null)
                {
                    throw new ArgumentException(string.Format("Type: {0} has not Parse static method!", type));
                }
                executor = new DynamicMethodExecutor(parseMethod);
                executorCache[type] = executor;
            }
            return executor.Execute(null, new object[] { value });
        }


        private class DynamicMethodExecutor
        {
            private Func<object, object[], object> m_execute;

            public DynamicMethodExecutor(MethodInfo methodInfo)
            {
                this.m_execute = this.GetExecuteDelegate(methodInfo);
            }

            public object Execute(object instance, object[] parameters)
            {
                return this.m_execute(instance, parameters);
            }

            private Func<object, object[], object> GetExecuteDelegate(MethodInfo methodInfo)
            {
                // parameters to execute
                ParameterExpression instanceParameter =
                    Expression.Parameter(typeof(object), "instance");
                ParameterExpression parametersParameter =
                    Expression.Parameter(typeof(object[]), "parameters");

                // build parameter list
                List<Expression> parameterExpressions = new List<Expression>();
                ParameterInfo[] paramInfos = methodInfo.GetParameters();
                for (int i = 0; i < paramInfos.Length; i++)
                {
                    // (Ti)parameters[i]
                    BinaryExpression valueObj = Expression.ArrayIndex(
                        parametersParameter, Expression.Constant(i));
                    UnaryExpression valueCast = Expression.Convert(
                        valueObj, paramInfos[i].ParameterType);

                    parameterExpressions.Add(valueCast);
                }

                // non-instance for static method, or ((TInstance)instance)
                Expression instanceCast = methodInfo.IsStatic ? null :
                    Expression.Convert(instanceParameter, methodInfo.ReflectedType);


                // static invoke or ((TInstance)instance).Method
                MethodCallExpression methodCall = Expression.Call(
                    instanceCast, methodInfo, parameterExpressions);

                // ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...)
                if (methodCall.Type == typeof(void))
                {
                    Expression<Action<object, object[]>> lambda =
                        Expression.Lambda<Action<object, object[]>>(
                            methodCall, instanceParameter, parametersParameter);

                    Action<object, object[]> execute = lambda.Compile();
                    return (instance, parameters) =>
                    {
                        execute(instance, parameters);
                        return null;
                    };
                }
                else
                {
                    UnaryExpression castMethodCall = Expression.Convert(
                        methodCall, typeof(object));
                    Expression<Func<object, object[], object>> lambda =
                        Expression.Lambda<Func<object, object[], object>>(
                            castMethodCall, instanceParameter, parametersParameter);

                    return lambda.Compile();
                }
            }
        }
    }

 

posted @ 2012-08-27 22:51  Bug山Bug海  阅读(335)  评论(0编辑  收藏  举报