GetConversion() публичный статический Метод

public static GetConversion ( Expression input, Type type ) : Expression
input System.Linq.Expressions.Expression
type System.Type
Результат System.Linq.Expressions.Expression
        static LambdaExpression OptionalConversion(Type type, ExcelParameterRegistration paramReg, bool treatEmptyAsMissing, bool treatNAErrorAsMissing)
        {
            // Decide whether to return a conversion function for this parameter
            if (!paramReg.CustomAttributes.OfType <OptionalAttribute>().Any())
            {
                return(null);
            }

            var defaultAttribute = paramReg.CustomAttributes.OfType <DefaultParameterValueAttribute>().FirstOrDefault();
            var defaultValue     = defaultAttribute == null?TypeConversion.GetDefault(type) : defaultAttribute.Value;

            // var returnType = type.GetGenericArguments()[0]; // E.g. returnType is double

            // Consume the attributes
            paramReg.CustomAttributes.RemoveAll(att => att is OptionalAttribute);
            paramReg.CustomAttributes.RemoveAll(att => att is DefaultParameterValueAttribute);

            // Here's the actual conversion function
            var input = Expression.Parameter(typeof(object), "input");

            return
                (Expression.Lambda(
                     Expression.Condition(
                         MissingTest(input, treatEmptyAsMissing, treatNAErrorAsMissing),
                         Expression.Constant(defaultValue, type),
                         TypeConversion.GetConversion(input, type)),
                     input));
        }
        internal static LambdaExpression NullableConversion(
            ParameterConversionConfiguration config, Type type,
            ExcelParameterRegistration paramReg, bool treatEmptyAsMissing,
            bool treatNAErrorAsMissing)
        {
            // Decide whether to return a conversion function for this parameter
            if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Nullable <>))
            {
                return(null);
            }

            var innerType = type.GetGenericArguments()[0]; // E.g. innerType is Complex
            LambdaExpression innerTypeConversion = ParameterConversionRegistration.GetParameterConversion(config, innerType, paramReg) ??
                                                   TypeConversion.GetConversion(typeof(object), innerType);
            ParameterExpression input = innerTypeConversion.Parameters[0];
            // Here's the actual conversion function
            var result =
                Expression.Lambda(
                    Expression.Condition(
                        // if the value is missing (or possibly empty)
                        MissingTest(input, treatEmptyAsMissing, treatNAErrorAsMissing),
                        // cast null to int?
                        Expression.Constant(null, type),
                        // else convert to int, and cast that to int?
                        Expression.Convert(Expression.Invoke(innerTypeConversion, input), type)),
                    input);

            return(result);
        }
        internal static LambdaExpression NullableConversion(
            IEnumerable <ParameterConversionConfiguration.ParameterConversion> parameterConversions, Type type,
            ExcelParameterRegistration paramReg, bool treatEmptyAsMissing,
            bool treatNAErrorAsMissing)
        {
            // Decide whether to return a conversion function for this parameter
            if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Nullable <>))
            {
                return(null);
            }

            var innerType = type.GetGenericArguments()[0]; // E.g. innerType is Complex

            // Try to find a converter for innerType in the config
            ParameterConversionConfiguration.ParameterConversion innerTypeParameterConversion = null;
            if (parameterConversions != null)
            {
                innerTypeParameterConversion =
                    parameterConversions.FirstOrDefault(c => c.Convert(innerType, paramReg) != null);
            }
            ParameterExpression input = null;
            Expression          innerTypeConversion = null;

            // if we have a converter for innertype in the config, then use it. Otherwise try one of the conversions for the basic types
            if (innerTypeParameterConversion == null)
            {
                input = Expression.Parameter(typeof(object), "input");
                innerTypeConversion = TypeConversion.GetConversion(input, innerType);
            }
            else
            {
                var innerTypeParamConverter = innerTypeParameterConversion.Convert(innerType, paramReg);
                input = Expression.Parameter(innerTypeParamConverter.Parameters[0].Type, "input");
                innerTypeConversion = Expression.Invoke(innerTypeParamConverter, input);
            }
            // Here's the actual conversion function
            var result =
                Expression.Lambda(
                    Expression.Condition(
                        // if the value is missing (or possibly empty)
                        MissingTest(input, treatEmptyAsMissing, treatNAErrorAsMissing),
                        // cast null to int?
                        Expression.Constant(null, type),
                        // else convert to int, and cast that to int?
                        Expression.Convert(innerTypeConversion, type)),
                    input);

            return(result);
        }
        // Implementations
        static LambdaExpression NullableConversion(Type type, ExcelParameterRegistration paramReg, bool treatEmptyAsMissing)
        {
            // Decide whether to return a conversion function for this parameter
            if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Nullable <>))                 // E.g. type is Nullable<double>
            {
                return(null);
            }

            var innerType = type.GetGenericArguments()[0]; // E.g. innerType is double
            // Here's the actual conversion function
            var input  = Expression.Parameter(typeof(object));
            var result =
                Expression.Lambda(
                    Expression.Condition(
                        // if the value is missing (or possibly empty)
                        MissingTest(input, treatEmptyAsMissing),
                        // cast null to int?
                        Expression.Constant(null, type),
                        // else convert to int, and cast that to int?
                        Expression.Convert(TypeConversion.GetConversion(input, innerType), type)),
                    input);

            return(result);
        }
Пример #5
0
        static LambdaExpression WrapMethodParams(LambdaExpression functionLambda)
        {
            /* We are converting:
             *     [ExcelFunction(...)]
             *     public static string myFunc(string input, int otherInput, params object[] args)
             *     {
             *          ...
             *     }
             *
             * into:
             *     [ExcelFunction(...)]
             *     public static string myFunc(string input, int otherInput, object arg1, object arg2, object arg3, object arg4, {...until...}, object arg253)
             *     {
             *         List<object> args = new List<object>();
             *         if (!(arg1 is ExcelMissing)) args.Add(arg1);
             *         if (!(arg2 is ExcelMissing)) args.Add(arg2);
             *         ...
             *         if (!(arg253 is ExcelMissing)) args.Add(arg253);
             *
             *         Array<object> argsArray = args.ToArray();
             *         return myFunc(input, otherInput, argsArray);
             *     }
             *
             *
             */

            int maxArguments;

            if (ExcelDnaUtil.ExcelVersion >= 12.0)
            {
                maxArguments = 125; // Constrained by 255 char registration string, take off 3 type chars, use up to 2 chars per param (before we start doing object...) (& also return)
                                    // CONSIDER: Might improve this if we generate the delegate based on the max length...
            }
            else
            {
                maxArguments = 29; // Or maybe 30?
            }

            var normalParams     = functionLambda.Parameters.Take(functionLambda.Parameters.Count() - 1).ToList();
            var normalParamCount = normalParams.Count;
            var paramsParamCount = maxArguments - normalParamCount;
            var paramsParamExprs = new List <ParameterExpression>(normalParams);
            var blockExprs       = new List <Expression>();
            var blockVars        = new List <ParameterExpression>();

            // We know that last parameter is an array type
            var argsArrayType   = functionLambda.Parameters.Last().Type;
            var argsType        = argsArrayType.GetElementType();
            var argsListType    = typeof(List <>).MakeGenericType(argsType);
            var argsListVarExpr = Expression.Variable(argsListType);

            blockVars.Add(argsListVarExpr);
            var argListAssignExpr = Expression.Assign(argsListVarExpr, Expression.New(argsListType));

            blockExprs.Add(argListAssignExpr);
            for (int i = 1; i <= paramsParamCount; i++)
            {
                var paramExpr = Expression.Parameter(typeof(object), "arg" + i);
                paramsParamExprs.Add(paramExpr);
                var testParam = Expression.IfThen(Expression.Not(Expression.TypeIs(paramExpr, typeof(ExcelMissing))),
                                                  Expression.Call(argsListVarExpr, "Add", null,
                                                                  TypeConversion.GetConversion(paramExpr, argsType)));
                blockExprs.Add(testParam);
            }
            var argArrayVarExpr = Expression.Variable(argsArrayType);

            blockVars.Add(argArrayVarExpr);

            var argArrayAssignExpr = Expression.Assign(argArrayVarExpr, Expression.Call(argsListVarExpr, "ToArray", null));

            blockExprs.Add(argArrayAssignExpr);

            var innerParams = new List <Expression>(normalParams)
            {
                argArrayVarExpr
            };
            var callInner = Expression.Invoke(functionLambda, innerParams);

            blockExprs.Add(callInner);

            var blockExpr = Expression.Block(blockVars, blockExprs);

            // Build the delegate type to return
            var allParamTypes = normalParams.Select(pi => pi.Type).ToList();
            var toAdd         = maxArguments - allParamTypes.Count;

            for (int i = 0; i < toAdd; i++)
            {
                allParamTypes.Add(typeof(object));
            }
            allParamTypes.Add(functionLambda.ReturnType);

            Type delegateType;

            if (maxArguments == 125)
            {
                delegateType = typeof(CustomFunc125 <, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,>)
                               .MakeGenericType(allParamTypes.ToArray());
            }
            else // if (maxArguments == 29)
            {
                delegateType = typeof(CustomFunc29 <, , , , , , , , , , , , , , , , , , , , , , , , , , , , ,>)
                               .MakeGenericType(allParamTypes.ToArray());
            }
            return(Expression.Lambda(delegateType, blockExpr, paramsParamExprs));
        }
Пример #6
0
        static LambdaExpression WrapMethodParams(LambdaExpression functionLambda)
        {
            /* We are converting:
             *     [ExcelFunction(...)]
             *     public static string myFunc(string input, int otherInput, params object[] args)
             *     {
             *          ...
             *     }
             *
             * into:
             *     [ExcelFunction(...)]
             *     public static string myFunc(string input, int otherInput, object arg3, object arg4, object arg5, object arg6, {...until...}, object arg125)
             *     {
             *         // First we figure where in the list to stop building the param array
             *         int lastArgToAdd = 0;
             *         if (!(arg3 is ExcelMissing)) lastArgToAdd = 3;
             *         if (!(arg4 is ExcelMissing)) lastArgToAdd = 4;
             *         ...
             *         if (!(arg125 is ExcelMissing)) lastArgToAdd = 125;
             *
             *         // Then add until we get there
             *         List<object> args = new List<object>();
             *         if (lastArgToAdd >= 3) args.Add(arg3);
             *         if (lastArgToAdd >= 4) args.Add(arg4);
             *         ...
             *         if (lastArgToAdd >= 125) args.Add(arg125);
             *
             *         Array<object> argsArray = args.ToArray();
             *         return myFunc(input, otherInput, argsArray);
             *     }
             *
             *
             */

            int maxArguments;

            if (ExcelDnaUtil.ExcelVersion >= 12.0)
            {
                maxArguments = 125; // Constrained by 255 char registration string, take off 3 type chars, use up to 2 chars per param (before we start doing object...) (& also return)
                                    // CONSIDER: Might improve this if we generate the delegate based on the max length...
            }
            else
            {
                maxArguments = 29; // Or maybe 30?
            }

            var normalParams     = functionLambda.Parameters.Take(functionLambda.Parameters.Count() - 1).ToList();
            var normalParamCount = normalParams.Count;
            var paramsParamCount = maxArguments - normalParamCount;
            var allParamExprs    = new List <ParameterExpression>(normalParams);
            var blockExprs       = new List <Expression>();
            var blockVars        = new List <ParameterExpression>();

            // Run through the arguments looking for the position of the last non-ExcelMissing argument
            var lastArgVarExpr = Expression.Variable(typeof(int));

            blockVars.Add(lastArgVarExpr);
            blockExprs.Add(Expression.Assign(lastArgVarExpr, Expression.Constant(0)));
            for (int i = normalParamCount + 1; i <= maxArguments; i++)
            {
                allParamExprs.Add(Expression.Parameter(typeof(object), "arg" + i));

                var lenTestParam = Expression.IfThen(Expression.Not(Expression.TypeIs(allParamExprs[i - 1], typeof(ExcelMissing))),
                                                     Expression.Assign(lastArgVarExpr, Expression.Constant(i)));
                blockExprs.Add(lenTestParam);
            }

            // We know that last parameter is an array type
            // Create a new list to hold the values
            var argsArrayType   = functionLambda.Parameters.Last().Type;
            var argsType        = argsArrayType.GetElementType();
            var argsListType    = typeof(List <>).MakeGenericType(argsType);
            var argsListVarExpr = Expression.Variable(argsListType);

            blockVars.Add(argsListVarExpr);
            var argListAssignExpr = Expression.Assign(argsListVarExpr, Expression.New(argsListType));

            blockExprs.Add(argListAssignExpr);
            // And put the (converted) arguments into the list
            for (int i = normalParamCount + 1; i <= maxArguments; i++)
            {
                var testParam = Expression.IfThen(Expression.GreaterThanOrEqual(lastArgVarExpr, Expression.Constant(i)),
                                                  Expression.Call(argsListVarExpr, "Add", null,
                                                                  TypeConversion.GetConversion(allParamExprs[i - 1], argsType)));

                blockExprs.Add(testParam);
            }
            var argArrayVarExpr = Expression.Variable(argsArrayType);

            blockVars.Add(argArrayVarExpr);

            var argArrayAssignExpr = Expression.Assign(argArrayVarExpr, Expression.Call(argsListVarExpr, "ToArray", null));

            blockExprs.Add(argArrayAssignExpr);

            var innerParams = new List <Expression>(normalParams)
            {
                argArrayVarExpr
            };
            var callInner = Expression.Invoke(functionLambda, innerParams);

            blockExprs.Add(callInner);

            var blockExpr = Expression.Block(blockVars, blockExprs);

            // Build the delegate type to return
            var allParamTypes = normalParams.Select(pi => pi.Type).ToList();
            var toAdd         = maxArguments - allParamTypes.Count;

            for (int i = 0; i < toAdd; i++)
            {
                allParamTypes.Add(typeof(object));
            }
            allParamTypes.Add(functionLambda.ReturnType);

            Type delegateType;

            if (maxArguments == 125)
            {
                delegateType = typeof(CustomFunc125 <, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,>)
                               .MakeGenericType(allParamTypes.ToArray());
            }
            else // if (maxArguments == 29)
            {
                delegateType = typeof(CustomFunc29 <, , , , , , , , , , , , , , , , , , , , , , , , , , , , ,>)
                               .MakeGenericType(allParamTypes.ToArray());
            }
            return(Expression.Lambda(delegateType, blockExpr, allParamExprs));
        }