ExpressionServices.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Expressions / ExpressionServices.cs / 1305376 / ExpressionServices.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

namespace System.Activities.Expressions 
{
    using System; 
    using System.Activities.Statements; 
    using System.Linq;
    using System.Linq.Expressions; 
    using System.Reflection;
    using System.Runtime;
    using System.Collections.ObjectModel;
    using System.Diagnostics.CodeAnalysis; 
    using System.Collections;
 
    public static class ExpressionServices 
    {
        // Reflection is used to call generic function because type information are only known at runtime. 
        static MethodInfo TryConvertBinaryExpressionHandle = typeof(ExpressionServices).GetMethod("TryConvertBinaryExpressionWorker", BindingFlags.NonPublic | BindingFlags.Static);
        static MethodInfo TryConvertUnaryExpressionHandle = typeof(ExpressionServices).GetMethod("TryConvertUnaryExpressionWorker", BindingFlags.NonPublic | BindingFlags.Static);
        static MethodInfo TryConvertMemberExpressionHandle = typeof(ExpressionServices).GetMethod("TryConvertMemberExpressionWorker", BindingFlags.NonPublic | BindingFlags.Static);
        static MethodInfo TryConvertArgumentExpressionHandle = typeof(ExpressionServices).GetMethod("TryConvertArgumentExpressionWorker", BindingFlags.NonPublic | BindingFlags.Static); 
        static MethodInfo TryConvertReferenceMemberExpressionHandle = typeof(ExpressionServices).GetMethod("TryConvertReferenceMemberExpressionWorker", BindingFlags.NonPublic | BindingFlags.Static);
        static MethodInfo TryConvertIndexerReferenceHandle = typeof(ExpressionServices).GetMethod("TryConvertIndexerReferenceWorker", BindingFlags.NonPublic | BindingFlags.Static); 
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "The parameter is restricted correctly.")] 
        public static Activity Convert(Expression> expression)
        {
            Activity result;
            if (expression == null) 
            {
                throw FxTrace.Exception.AsError(new ArgumentNullException("expression", SR.ExpressionRequiredForConversion)); 
            } 
            TryConvert(expression.Body, true, out result);
            return result; 
        }

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "The parameter is restricted correctly.")] 
        public static bool TryConvert(Expression> expression, out Activity result)
        { 
            if (expression == null) 
            {
                result = null; 
                return false;
            }
            return TryConvert(expression.Body, false, out result) == null;
        } 

        static string TryConvert(Expression body, bool throwOnError, out Activity result) 
        { 
            result = null;
            UnaryExpression unaryExpressionBody = body as UnaryExpression; 
            if (unaryExpressionBody != null)
            {
                Type operandType = unaryExpressionBody.Operand.Type;
                Type resultType = typeof(TResult); 
                return TryConvertUnaryExpression(unaryExpressionBody, operandType, throwOnError, out result);
            } 
            BinaryExpression binaryExpressionBody = body as BinaryExpression; 
            if (binaryExpressionBody != null)
            { 
                Type leftType = binaryExpressionBody.Left.Type;
                Type rightType = binaryExpressionBody.Right.Type;
                if (binaryExpressionBody.NodeType == ExpressionType.ArrayIndex)
                { 
                   return TryConvertArrayItemValue(binaryExpressionBody, leftType, rightType, throwOnError, out result);
                } 
                return TryConvertBinaryExpression(binaryExpressionBody, leftType, rightType, throwOnError, out result); 
            }
            MemberExpression memberExpressionBody = body as MemberExpression; 
            if (memberExpressionBody != null)
            {
                Type memberType = memberExpressionBody.Expression == null ? memberExpressionBody.Member.DeclaringType : memberExpressionBody.Expression.Type;
                return TryConvertMemberExpression(memberExpressionBody, memberType, throwOnError, out result); 
            }
            MethodCallExpression methodCallExpressionBody = body as MethodCallExpression; 
            if (methodCallExpressionBody != null) 
            {
                MethodInfo calledMethod = methodCallExpressionBody.Method; 
                Type declaringType = calledMethod.DeclaringType;
                ParameterInfo[] parameters = calledMethod.GetParameters();
                if (TypeHelper.AreTypesCompatible(declaringType, typeof(Variable)) && calledMethod.Name == "Get" && parameters.Length == 1 && TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(ActivityContext)))
                { 

                    return TryConvertVariableValue(methodCallExpressionBody, throwOnError, out result); 
                } 
                else if (TypeHelper.AreTypesCompatible(declaringType, typeof(Argument))
                     && calledMethod.Name == "Get" && parameters.Length == 1 && TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(ActivityContext))) 
                {
                    return TryConvertArgumentValue(methodCallExpressionBody.Object as MemberExpression, throwOnError, out result);
                }
                else if (TypeHelper.AreTypesCompatible(declaringType, typeof(DelegateArgument)) 
                    && calledMethod.Name == "Get" && parameters.Length == 1 && TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(ActivityContext)))
                { 
                    return TryConvertDelegateArgumentValue(methodCallExpressionBody, throwOnError, out result); 
                }
                //Only ActivityContext.GetValue() on Argument, RuntimeArgument are supported. 
                //The reason why DelegateArgument and Variable are not supported: for such usage: ctx.GetValue(delegateInArgument),
                //C# compiler will complain ambiguous method resolution between ActivityContext.GetValue(Argument) and ActivityContext.GetValue(LocationReference).
                //If we use ctx.GetValue((LocationReference)delegateInArgument)instead, we cannot tell whether it's a DelegateArgument.
                // Variable has similar issue. 
                else if (TypeHelper.AreTypesCompatible(declaringType, typeof(ActivityContext)) && calledMethod.Name == "GetValue" && parameters.Length == 1 &&
                (TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(Argument)) || TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(RuntimeArgument)))) 
                { 
                    MemberExpression memberExpression = methodCallExpressionBody.Arguments[0] as MemberExpression;
                    return TryConvertArgumentValue(memberExpression, throwOnError, out result); 
                }
                else
                {
                    return TryConvertMethodCallExpression(methodCallExpressionBody, throwOnError, out result); 
                }
            } 
            InvocationExpression invocationExpression = body as InvocationExpression; 
            if (invocationExpression != null)
            { 
                return TryConvertInvocationExpression(invocationExpression, throwOnError, out result);
            }
            NewExpression newExpression = body as NewExpression;
            if (newExpression != null) 
            {
                return TryConvertNewExpression(newExpression, throwOnError, out result); 
            } 
            NewArrayExpression newArrayExpression = body as NewArrayExpression;
            if (newArrayExpression != null && newArrayExpression.NodeType != ExpressionType.NewArrayInit) 
            {
                return TryConvertNewArrayExpression(newArrayExpression, throwOnError, out result);
            }
            ConstantExpression constantExpressionBody = body as ConstantExpression; 
            if (constantExpressionBody != null)
            { 
                // This is to handle the leaf node as a literal value 
                result = new Literal { Value = (TResult)constantExpressionBody.Value };
                return null; 
            }
            if (throwOnError)
            {
                throw FxTrace.Exception.AsError(new NotSupportedException(SR.UnsupportedExpressionType(body.NodeType))); 
            }
            else 
            { 
                return SR.UnsupportedExpressionType(body.NodeType);
            } 
        }

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "The parameter is restricted correctly.")] 
        public static Activity> ConvertReference(Expression> expression)
        { 
            Activity> result; 
            if (expression == null)
            { 
                throw FxTrace.Exception.AsError(new ArgumentNullException("expression", SR.ExpressionRequiredForConversion));
            }

            TryConvertReference(expression.Body, true, out result); 
            return result;
        } 
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
            Justification = "The parameter is restricted correctly.")] 
        public static bool TryConvertReference(Expression> expression, out Activity> result)
        {
            if (expression == null)
            { 
                result = null;
                return false; 
            } 
            return TryConvertReference(expression.Body, false, out result) == null;
        } 

        static string TryConvertReference(Expression body, bool throwOnError, out Activity> result)
        {
            result = null; 
            MemberExpression memberExpressionBody = body as MemberExpression;
            if (memberExpressionBody != null) 
            { 
                Type memberType = memberExpressionBody.Expression == null ? memberExpressionBody.Member.DeclaringType : memberExpressionBody.Expression.Type;
                return TryConvertReferenceMemberExpression(memberExpressionBody, memberType, throwOnError, out result); 
            }
            BinaryExpression binaryExpressionBody = body as BinaryExpression;
            if (binaryExpressionBody != null)
            { 
                Type leftType = binaryExpressionBody.Left.Type;
                Type rightType = binaryExpressionBody.Right.Type; 
                if (binaryExpressionBody.NodeType == ExpressionType.ArrayIndex) 
                {
                    return TryConvertArrayItemReference(binaryExpressionBody, leftType, rightType, throwOnError, out result); 
                }
            }
            MethodCallExpression methodCallExpressionBody = body as MethodCallExpression;
            if (methodCallExpressionBody != null) 
            {
                Type declaringType = methodCallExpressionBody.Method.DeclaringType; 
                MethodInfo calledMethod = methodCallExpressionBody.Method; 
                if (declaringType.IsArray && calledMethod.Name == "Get")
                { 
                    return TryConvertMultiDimensionalArrayItemReference(methodCallExpressionBody, throwOnError, out result);
                }

                if (calledMethod.IsSpecialName && calledMethod.Name == "get_Item") 
                {
                    return TryConvertIndexerReference(methodCallExpressionBody, throwOnError, out result); 
                } 

                ParameterInfo[] parameters = calledMethod.GetParameters(); 
                if (TypeHelper.AreTypesCompatible(declaringType, typeof(Variable)) && calledMethod.Name == "Get" && parameters.Length == 1 && TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(ActivityContext)))
                {
                    return TryConvertVariableReference(methodCallExpressionBody, throwOnError, out result);
                } 
                else if (TypeHelper.AreTypesCompatible(declaringType, typeof(Argument))
                     && calledMethod.Name == "Get" && parameters.Length == 1 && TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(ActivityContext))) 
                { 
                    return TryConvertArgumentReference(methodCallExpressionBody, throwOnError, out result);
                } 
                else if (TypeHelper.AreTypesCompatible(declaringType, typeof(DelegateArgument))
                    && calledMethod.Name == "Get" && parameters.Length == 1 && TypeHelper.AreTypesCompatible(parameters[0].ParameterType, typeof(ActivityContext)))
                {
                    return TryConvertDelegateArgumentReference(methodCallExpressionBody, throwOnError, out result); 
                }
            } 
            if (throwOnError) 
            {
                throw FxTrace.Exception.AsError(new NotSupportedException(SR.UnsupportedReferenceExpressionType(body.NodeType))); 
            }
            else
            {
                return SR.UnsupportedReferenceExpressionType(body.NodeType); 
            }
        } 
 
        static string TryConvertIndexerReference(MethodCallExpression methodCallExpressionBody, bool throwOnError, out Activity> result)
        { 
            result = null;
            try
            {
                if (methodCallExpressionBody.Object == null) 
                {
                    if (throwOnError) 
                    { 
                        throw FxTrace.Exception.AsError(new ValidationException(SR.InstanceMethodCallRequiresTargetObject));
                    } 
                    else
                    {
                        return SR.InstanceMethodCallRequiresTargetObject;
                    } 
                }
                MethodInfo specializedHandle = TryConvertIndexerReferenceHandle.MakeGenericMethod(methodCallExpressionBody.Object.Type, typeof(TResult)); 
                object[] parameters = new object[] { methodCallExpressionBody, throwOnError, null }; 
                string errorString = specializedHandle.Invoke(null, parameters) as string;
                result = parameters[2] as Activity>; 
                return errorString;
            }
            catch (TargetInvocationException e)
            { 
                throw FxTrace.Exception.AsError(e.InnerException);
            } 
        } 

        static string TryConvertIndexerReferenceWorker(MethodCallExpression methodCallExpressionBody, bool throwOnError, out Activity> result) 
        {
            result = null;
            Fx.Assert(methodCallExpressionBody.Object != null, "Indexer must have a target object");
            if (!typeof(TOperand).IsValueType) 
            {
                Activity operand = null; 
                string operandError = TryConvert(methodCallExpressionBody.Object, throwOnError, out operand); 
                if (operandError != null)
                { 
                    return operandError;
                }
                IndexerReference indexerReference = new IndexerReference
                { 
                    Operand = new InArgument(operand) { EvaluationOrder = 0 },
                }; 
                string argumentError = TryConvertArguments(methodCallExpressionBody.Arguments, indexerReference.Indices, methodCallExpressionBody.GetType(), 1, null, throwOnError); 
                if (argumentError != null)
                { 
                    return argumentError;
                }
                result = indexerReference;
 
            }
            else 
            { 
                Activity> operandReference = null;
                string operandError = TryConvertReference(methodCallExpressionBody.Object, throwOnError, out operandReference); 
                if (operandError != null)
                {
                    return operandError;
                } 
                ValueTypeIndexerReference indexerReference = new ValueTypeIndexerReference
                { 
                    OperandLocation = new InOutArgument(operandReference) { EvaluationOrder = 0 }, 
                };
                string argumentError = TryConvertArguments(methodCallExpressionBody.Arguments, indexerReference.Indices, methodCallExpressionBody.GetType(), 1, null, throwOnError); 
                if (argumentError != null)
                {
                    return argumentError;
                } 
                result = indexerReference;
            } 
            return null; 
        }
 
        static string TryConvertMultiDimensionalArrayItemReference(MethodCallExpression methodCallExpression, bool throwOnError, out Activity> result)
        {
            result = null;
            Activity operand; 
            if (methodCallExpression.Object == null)
            { 
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(new ValidationException(SR.InstanceMethodCallRequiresTargetObject)); 
                }
                else
                {
                    return SR.InstanceMethodCallRequiresTargetObject; 
                }
            } 
            string errorString = TryConvert(methodCallExpression.Object, throwOnError, out operand); 
            if (errorString != null)
            { 
                return errorString;
            }

            MultidimensionalArrayItemReference reference = new MultidimensionalArrayItemReference 
            {
                Array = new InArgument(operand) { EvaluationOrder = 0 }, 
            }; 

            Collection> arguments = reference.Indices; 
            string argumentError = TryConvertArguments(methodCallExpression.Arguments, reference.Indices, methodCallExpression.GetType(), 1, null, throwOnError);
            if (argumentError != null)
            {
                return argumentError; 
            }
            result = reference; 
            return null; 

        } 

        static string TryConvertVariableReference(MethodCallExpression methodCallExpression, bool throwOnError, out Activity> result)
        {
            result = null; 
            Variable variableObject = null;
 
            // 
            // This is a fast path to handle a simple variable object.
            // 
            // Linq actually generate a temp class wrapping all the local variables.
            //
            // The real expression object look like
            // new TempClass() { A = a }.A.Get(env) 
            //
            // A is a field 
 
            if (methodCallExpression.Object is MemberExpression)
            { 
                MemberExpression member = methodCallExpression.Object as MemberExpression;
                if (member.Expression is ConstantExpression)
                {
                    ConstantExpression memberExpression = member.Expression as ConstantExpression; 
                    if (member.Member is FieldInfo)
                    { 
                        FieldInfo field = member.Member as FieldInfo; 
                        variableObject = field.GetValue(memberExpression.Value) as Variable;
                        Fx.Assert(variableObject != null, "Linq generated expression tree should be correct"); 
                        result = new VariableReference { Variable = variableObject };
                        return null;
                    }
                } 
            }
 
            //This is to handle the expression whose evaluation result is a variable object. 
            //Limitation: The expression of variable object has to be evaludated in conversion time. It means after conversion, the variable object should not be changed any more.
            //For example, the following case is not legal: 
            //
            //Program.static_X = new Variable { Default = "Hello" };
            //Activity> weRef = ExpressionServices.ConvertReference((env) => Program.static_X.Get(env));
            //Program.static_X = new Variable { Default = "World" }; 
            //Sequence sequence = new Sequence
            //{ 
            //    Variables = { Program.static_X }, 
            //    Activities =
            //      { 
            //         new Assign
            //         {
            //             To = new OutArgument{Expression = weRef},
            //             Value = "haha", 
            //         },
            //         new WriteLine 
            //         { 
            //             Text = Program.static_X,
            //         } 
            //      }
            //};
            //WorkflowInvoker.Invoke(sequence);
            // 
            // The reason is that "Program.static_X = new Variable { Default = "World" }" happens after conversion.
            try 
            { 
                Expression> funcExpression = Expression.Lambda>(methodCallExpression.Object);
                Func func = funcExpression.Compile(); 
                variableObject = func();
            }
            catch (Exception e)
            { 
                if (Fx.IsFatal(e))
                { 
                    throw; 
                }
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(e);
                }
                else 
                {
                    return e.Message; 
                } 
            }
            Fx.Assert(variableObject is Variable, "Linq generated expression tree should be correct"); 
            result = new VariableReference { Variable = variableObject };
            return null;
        }
 
        static string TryConvertArrayItemReference(BinaryExpression binaryExpression, Type leftType, Type rightType, bool throwOnError, out Activity> result)
        { 
            result = null; 

            //for ArrayIndex expression, Left type is always TResult[] and Right type is always int 
            if (!leftType.IsArray)
            {
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.DoNotSupportArrayIndexerOnNonArrayType(leftType)));
                } 
                else 
                {
                    return SR.DoNotSupportArrayIndexerOnNonArrayType(leftType); 
                }
            }
            //Because co-variance for LValue requires that TResult is compatible with actual type. However, we cannot write such a lambda expression. E,g:
            //Expression expr = env => a.Get(env). Here a.Get(env) returns BaseClass.  So we needn't co-viariance here. 
            if (leftType.GetElementType() != typeof(TResult))
            { 
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.DoNotSupportArrayIndexerReferenceWithDifferentArrayTypeAndResultType(leftType, typeof(TResult)))); 
                }
                else
                {
                    return SR.DoNotSupportArrayIndexerReferenceWithDifferentArrayTypeAndResultType(leftType, typeof(TResult)); 
                }
            } 
            if (rightType != typeof(int)) 
            {
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.DoNotSupportArrayIndexerWithNonIntIndex(rightType)));
                }
                else 
                {
                    return SR.DoNotSupportArrayIndexerWithNonIntIndex(rightType); 
                } 
            }
 
            Activity array;
            string arrayError = TryConvert(binaryExpression.Left, throwOnError, out array);
            if (arrayError != null)
            { 
                return arrayError;
            } 
 
            Activity index;
            string indexError = TryConvert(binaryExpression.Right, throwOnError, out index); 
            if (indexError != null)
            {
                return indexError;
            } 

            result = new ArrayItemReference 
            { 
                Array = new InArgument(array) { EvaluationOrder = 0 },
                Index = new InArgument(index) { EvaluationOrder = 1 }, 
            };
            return null;
        }
 
        static string TryConvertVariableValue(MethodCallExpression methodCallExpression, bool throwOnError, out Activity result)
        { 
            result = null; 
            Variable variableObject = null;
 
            //
            // This is a fast path to handle a simple variable object
            //
            // Linq actually generate a temp class wrapping all the local variables. 
            //
            // The real expression object look like 
            // new TempClass() { A = a }.A.Get(env) 
            //
            // A is a field 

            if (methodCallExpression.Object is MemberExpression)
            {
                MemberExpression member = methodCallExpression.Object as MemberExpression; 
                if (member.Expression is ConstantExpression)
                { 
                    ConstantExpression memberExpression = member.Expression as ConstantExpression; 
                    if (member.Member is FieldInfo)
                    { 
                        FieldInfo field = member.Member as FieldInfo;
                        variableObject = field.GetValue(memberExpression.Value) as Variable;
                        result = new VariableValue { Variable = variableObject };
                        return null; 
                    }
                } 
            } 

            //This is to handle the expression whose evaluation result is a variable object. 
            //Limitation: The expression of variable object has to be evaludated in conversion time. It means after conversion, the variable object should not be changed any more.
            //For example, the following case is not legal:
            //
            //  Program.static_X = new Variable { Default = "Hello" }; 
            //  Activity we = ExpressionServices.Convert((env) => Program.static_X.Get(env));
            //  Program.static_X = new Variable { Default = "World" }; 
            //  Sequence sequence = new Sequence 
            //  {
            //      Variables = { Program.static_X }, 
            //      Activities =
            //      {
            //             new WriteLine
            //          { 
            //                 Text = new InArgument{Expression = we},
            //          } 
            //      } 
            //  };
            //  WorkflowInvoker.Invoke(sequence); 
            //
            // The reason is that "Program.static_X = new Variable { Default = "World" }" happens after conversion.

            try 
            {
                Expression> funcExpression = Expression.Lambda>(methodCallExpression.Object); 
                Func func = funcExpression.Compile(); 
                variableObject = func();
            } 
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                { 
                    throw;
                } 
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(e); 
                }
                else
                {
                    return e.Message; 
                }
            } 
            result = new VariableValue { Variable = variableObject }; 
            return null;
        } 

        static string TryConvertDelegateArgumentValue(MethodCallExpression methodCallExpression, bool throwOnError, out Activity result)
        {
            result = null; 
            DelegateArgument delegateArgument = null;
 
            //This is to handle the expression whose evaluation result is a DelegateArgument. 
            //Limitation: The expression of variable object has to be evaluated in conversion time. It means after conversion, the DelegateArgument object should not be changed any more.
            //For example, the following case is not legal: 
            //
            //  Program.static_X = new DelegateInArgument();
            //  Activity we = ExpressionServices.Convert((env) => Program.static_X.Get(env));
            //  Program.static_X = new DelegateInArgument(); 
            //  ActivityAction activityAction = new ActivityAction
            //  { 
            //      Argument = Program.static_X, 
            //      Handler = new WriteLine
            //          { 
            //                 Text = we,
            //          }
            //      }
            //  }; 
            //  WorkflowInvoker.Invoke( new InvokeAction
            //                          { 
            //                              Argument = "Hello", 
            //                              Action = activityAction,
            //                          } 
            //);
            //
            // The reason is that "Program.static_X" is changed after conversion.
 
            try
            { 
                Expression> funcExpression = Expression.Lambda>(methodCallExpression.Object); 
                Func func = funcExpression.Compile();
                delegateArgument = func(); 
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e)) 
                {
                    throw; 
                } 
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(e);
                }
                else
                { 
                    return e.Message;
                } 
            } 
            result = new DelegateArgumentValue(delegateArgument);
            return null; 
        }

        static string TryConvertDelegateArgumentReference(MethodCallExpression methodCallExpression, bool throwOnError, out Activity> result)
        { 
            result = null;
            DelegateArgument delegateArgument = null; 
 
            //This is to handle the expression whose evaluation result is a DelegateArgument.
            //Limitation: The expression of variable object has to be evaluated in conversion time. It means after conversion, the DelegateArgument object should not be changed any more. 
            //For example, the following case is not legal:
            //
            //  Program.static_X = new DelegateInArgument();
            //  Activity we = ExpressionServices.Convert((env) => Program.static_X.Get(env)); 
            //  Program.static_X = new DelegateInArgument();
            //  ActivityAction activityAction = new ActivityAction 
            //  { 
            //      Argument = Program.static_X,
            //      Handler = new WriteLine 
            //          {
            //                 Text = we,
            //          }
            //      } 
            //  };
            //  WorkflowInvoker.Invoke( new InvokeAction 
            //                          { 
            //                              Argument = "Hello",
            //                              Action = activityAction, 
            //                          }
            //);
            //
            // The reason is that "Program.static_X" is changed after conversion. 

            try 
            { 
                Expression> funcExpression = Expression.Lambda>(methodCallExpression.Object);
                Func func = funcExpression.Compile(); 
                delegateArgument = func();
            }
            catch (Exception e)
            { 
                if (Fx.IsFatal(e))
                { 
                    throw; 
                }
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(e);
                }
                else 
                {
                    return e.Message; 
                } 
            }
            result = new DelegateArgumentReference(delegateArgument); 
            return null;
        }

        static string TryConvertArgumentValue(MemberExpression memberExpression, bool throwOnError, out Activity result) 
        {
            result = null; 
 
            if (memberExpression != null && TypeHelper.AreTypesCompatible(memberExpression.Type, typeof(RuntimeArgument)))
            { 
                RuntimeArgument ra = null;
                try
                {
                    Expression> expr = Expression.Lambda>(memberExpression, null); 
                    Func func = expr.Compile();
                    ra = func(); 
                } 
                catch (Exception e)
                { 
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    } 

                    return e.Message; 
                } 

                if (ra != null) 
                {
                    result = new ArgumentValue
                    {
                        ArgumentName = ra.Name, 
                    };
                    return null; 
                } 
                else
                { 
                    if (throwOnError)
                    {
                        throw FxTrace.Exception.AsError(new ValidationException(SR.RuntimeArgumentNotCreated));
                    } 
                    else
                    { 
                        return SR.RuntimeArgumentNotCreated; 
                    }
                } 

            }
            else
            { 
                //Assumption: Arguments must be properties of Activity object. Otherwise, it cannot be found by runtime via ArgumentValue.
                if (memberExpression != null && memberExpression.Member is PropertyInfo) 
                { 
                    PropertyInfo property = memberExpression.Member as PropertyInfo;
                    result = new ArgumentValue { ArgumentName = property.Name }; 
                    return null;
                }
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(new ValidationException(SR.ArgumentMustbePropertyofWorkflowElement));
                } 
                else 
                {
                    return SR.ArgumentMustbePropertyofWorkflowElement; 
                }
            }
         }
 
        static string TryConvertArgumentReference(MethodCallExpression methodCallExpression, bool throwOnError, out Activity> result)
        { 
            result = null; 
            //Assumption: Arguments must be properties of Activity object. Otherwise, it cannot be found by runtime via ArgumentReference.
            if (methodCallExpression.Object is MemberExpression) 
            {
                MemberExpression member = methodCallExpression.Object as MemberExpression;
                if (member.Member is PropertyInfo)
                { 
                    PropertyInfo property = member.Member as PropertyInfo;
                    result = new ArgumentReference { ArgumentName = property.Name }; 
                    return null; 
                }
            } 
            if (throwOnError)
            {
                throw FxTrace.Exception.AsError(new ValidationException(SR.ArgumentMustbePropertyofWorkflowElement));
            } 
            else
            { 
                return SR.ArgumentMustbePropertyofWorkflowElement; 
            }
        } 

        static string TryConvertBinaryExpression(BinaryExpression binaryExpressionBody, Type leftType, Type rightType, bool throwOnError, out Activity result)
        {
            try 
            {
                MethodInfo specializedHandle = TryConvertBinaryExpressionHandle.MakeGenericMethod(leftType, rightType, typeof(TResult)); 
                object[] parameters = new object[] { binaryExpressionBody, throwOnError, null }; 
                string errorString = specializedHandle.Invoke(null, parameters) as string;
                result = parameters[2] as Activity; 
                return errorString;
            }
            catch (TargetInvocationException e)
            { 
                throw FxTrace.Exception.AsError(e.InnerException);
            } 
        } 

        //this method handles single dimentional array. Multiple dimentional array accessor is method call expression 
        static string TryConvertArrayItemValue(BinaryExpression binaryExpression, Type leftType, Type rightType, bool throwOnError, out Activity result)
        {
            result = null;
 
            //for ArrayIndex expression, Left type is always TResult[] and Right type is always int
            if (!leftType.IsArray) 
            { 
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.DoNotSupportArrayIndexerOnNonArrayType(leftType)));
                }
                else
                { 
                    return SR.DoNotSupportArrayIndexerOnNonArrayType(leftType);
                } 
            } 
            if (!TypeHelper.AreTypesCompatible(leftType.GetElementType(), typeof(TResult)))
            { 
                if (throwOnError)
                {
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.DoNotSupportArrayIndexerValueWithIncompatibleArrayTypeAndResultType(leftType, typeof(TResult))));
                } 
                else
                { 
                    return SR.DoNotSupportArrayIndexerValueWithIncompatibleArrayTypeAndResultType(leftType, typeof(TResult)); 
                }
            } 
            if (rightType != typeof(int))
            {
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(new NotSupportedException(SR.DoNotSupportArrayIndexerWithNonIntIndex(rightType)));
                } 
                else 
                {
                    return SR.DoNotSupportArrayIndexerWithNonIntIndex(rightType); 
                }
            }

            Activity array; 
            string arrayError = TryConvert(binaryExpression.Left, throwOnError, out array);
            if (arrayError != null) 
            { 
                return arrayError;
            } 

            Activity index;
            string indexError = TryConvert(binaryExpression.Right, throwOnError, out index);
            if (indexError != null) 
            {
                return indexError; 
            } 

            result = new ArrayItemValue 
            {
                Array = new InArgument(array) { EvaluationOrder = 0 },
                Index = new InArgument(index) { EvaluationOrder = 1 },
            }; 
            return null;
        } 
 
        static string TryConvertBinaryExpressionWorker(BinaryExpression binaryExpressionBody, bool throwOnError, out Activity result)
        { 
            result = null;

            Activity left;
            string leftError = TryConvert(binaryExpressionBody.Left, throwOnError, out left); 
            if (leftError != null)
            { 
                return leftError; 
            }
            Activity right; 
            string rightError = TryConvert(binaryExpressionBody.Right, throwOnError, out right);
            if (rightError != null)
            {
                return rightError; 
            }
 
            if (binaryExpressionBody.Method != null) 
            {
                return TryConvertOverloadingBinaryOperator(binaryExpressionBody, left, right, throwOnError, out result); 
            }

            InArgument leftArgument = new InArgument(left) { EvaluationOrder = 0 };
            InArgument rightArgument = new InArgument(right) { EvaluationOrder = 1 }; 

            switch (binaryExpressionBody.NodeType) 
            { 
                case ExpressionType.Add:
                    result = new Add() { Left = leftArgument, Right = rightArgument, Checked = false }; 
                    break;
                case ExpressionType.AddChecked:
                    result = new Add() { Left = leftArgument, Right = rightArgument, Checked = true };
                    break; 
                case ExpressionType.Subtract:
                    result = new Subtract() { Left = leftArgument, Right = rightArgument, Checked = false }; 
                    break; 
                case ExpressionType.SubtractChecked:
                    result = new Subtract() { Left = leftArgument, Right = rightArgument, Checked = true }; 
                    break;
                case ExpressionType.Multiply:
                    result = new Multiply() { Left = leftArgument, Right = rightArgument, Checked = false };
                    break; 
                case ExpressionType.MultiplyChecked:
                    result = new Multiply() { Left = leftArgument, Right = rightArgument, Checked = true }; 
                    break; 
                case ExpressionType.Divide:
                    result = new Divide() { Left = leftArgument, Right = rightArgument }; 
                    break;
                case ExpressionType.AndAlso:
                    Fx.Assert(typeof(TLeft) == typeof(bool), "AndAlso only accept bool.");
                    Fx.Assert(typeof(TRight) == typeof(bool), "AndAlso only accept bool."); 
                    Fx.Assert(typeof(TResult) == typeof(bool), "AndAlso only accept bool.");
                    // Work around generic constraints 
                    object leftObject1 = left; 
                    object rightObject1 = right;
                    object resultObject1 = new AndAlso() { Left = (Activity)leftObject1, Right = (Activity)rightObject1 }; 
                    result = (Activity)resultObject1;
                    break;
                case ExpressionType.OrElse:
                    Fx.Assert(typeof(TLeft) == typeof(bool), "OrElse only accept bool."); 
                    Fx.Assert(typeof(TRight) == typeof(bool), "OrElse only accept bool.");
                    Fx.Assert(typeof(TResult) == typeof(bool), "OrElse only accept bool."); 
                    // Work around generic constraints 
                    object leftObject2 = left;
                    object rightObject2 = right; 
                    object resultObject2 = new OrElse() { Left = (Activity)leftObject2, Right = (Activity)rightObject2 };
                    result = (Activity)resultObject2;
                    break;
                case ExpressionType.Or: 
                    result = new Or() { Left = leftArgument, Right = rightArgument };
                    break; 
                case ExpressionType.And: 
                    result = new And() { Left = leftArgument, Right = rightArgument };
                    break; 
                case ExpressionType.LessThan:
                    result = new LessThan() { Left = leftArgument, Right = rightArgument };
                    break;
                case ExpressionType.LessThanOrEqual: 
                    result = new LessThanOrEqual() { Left = leftArgument, Right = rightArgument };
                    break; 
                case ExpressionType.GreaterThan: 
                    result = new GreaterThan() { Left = leftArgument, Right = rightArgument };
                    break; 
                case ExpressionType.GreaterThanOrEqual:
                    result = new GreaterThanOrEqual() { Left = leftArgument, Right = rightArgument };
                    break;
                case ExpressionType.Equal: 
                    result = new Equal() { Left = leftArgument, Right = rightArgument };
                    break; 
                case ExpressionType.NotEqual: 
                    result = new NotEqual() { Left = leftArgument, Right = rightArgument };
                    break; 
                default:
                    if (throwOnError)
                    {
                        throw FxTrace.Exception.AsError(new NotSupportedException(SR.UnsupportedExpressionType(binaryExpressionBody.NodeType))); 
                    }
                    else 
                    { 
                        return SR.UnsupportedExpressionType(binaryExpressionBody.NodeType);
                    } 
            }

            return null;
        } 

        static string TryConvertUnaryExpression(UnaryExpression unaryExpressionBody, Type operandType, bool throwOnError, out Activity result) 
        { 
            try
            { 
                MethodInfo specializedHandle = TryConvertUnaryExpressionHandle.MakeGenericMethod(operandType, typeof(TResult));
                object[] parameters = new object[] { unaryExpressionBody, throwOnError, null };
                string errorString = specializedHandle.Invoke(null, parameters) as string;
                result = parameters[2] as Activity; 
                return errorString;
            } 
            catch (TargetInvocationException e) 
            {
                throw FxTrace.Exception.AsError(e.InnerException); 
            }
        }

        static string TryConvertUnaryExpressionWorker(UnaryExpression unaryExpressionBody, bool throwOnError, out Activity result) 
        {
            result = null; 
 
            Activity operand;
            string operandError = TryConvert(unaryExpressionBody.Operand, throwOnError, out operand); 
            if (operandError != null)
            {
                return operandError;
            } 

            if (unaryExpressionBody.Method != null) 
            { 
                return TryConvertOverloadingUnaryOperator(unaryExpressionBody, operand, throwOnError, out result);
            } 

            switch (unaryExpressionBody.NodeType)
            {
                case ExpressionType.Not: 
                    result = new Not { Operand = operand };
                    break; 
                case ExpressionType.Convert: 
                    result = new Cast { Operand = operand, Checked = false };
                    break; 
                case ExpressionType.ConvertChecked:
                    result = new Cast { Operand = operand, Checked = true };
                    break;
                case ExpressionType.TypeAs: 
                    result = new As { Operand = operand };
                    break; 
                default: 
                    if (throwOnError)
                    { 
                        throw FxTrace.Exception.AsError(new NotSupportedException(SR.UnsupportedExpressionType(unaryExpressionBody.NodeType)));
                    }
                    else
                    { 
                        return SR.UnsupportedExpressionType(unaryExpressionBody.NodeType);
                    } 
            } 

            return null; 
        }

        static string TryConvertMemberExpression(MemberExpression memberExpressionBody, Type operandType, bool throwOnError, out Activity result)
        { 
            try
            { 
                MethodInfo specializedHandle = TryConvertMemberExpressionHandle.MakeGenericMethod(operandType, typeof(TResult)); 
                object[] parameters = new object[] { memberExpressionBody, throwOnError, null };
                string errorString = specializedHandle.Invoke(null, parameters) as string; 
                result = parameters[2] as Activity;
                return errorString;
            }
            catch (TargetInvocationException e) 
            {
                throw FxTrace.Exception.AsError(e.InnerException); 
            } 
        }
 
        static string TryConvertMemberExpressionWorker(MemberExpression memberExpressionBody, bool throwOnError, out Activity result)
        {
            result = null;
            Activity operand = null; 
            if (memberExpressionBody.Expression != null)
            { 
                // Static property might not have any expressions. 
                string operandError = TryConvert(memberExpressionBody.Expression, throwOnError, out operand);
                if (operandError != null) 
                {
                    return operandError;
                }
            } 
            if (memberExpressionBody.Member is PropertyInfo)
            { 
                if (operand == null) 
                {
                    result = new PropertyValue { PropertyName = memberExpressionBody.Member.Name }; 
                }
                else
                {
                    result = new PropertyValue { Operand = operand, PropertyName = memberExpressionBody.Member.Name }; 
                }
                return null; 
            } 
            else if (memberExpressionBody.Member is FieldInfo)
            { 
                if (operand == null)
                {
                    result = new FieldValue { FieldName = memberExpressionBody.Member.Name };
                } 
                else
                { 
                    result = new FieldValue { Operand = operand, FieldName = memberExpressionBody.Member.Name }; 
                }
                return null; 
            }
            if (throwOnError)
            {
                throw FxTrace.Exception.AsError(new NotSupportedException(SR.UnsupportedMemberExpressionWithType(memberExpressionBody.Member.GetType().Name))); 
            }
            else 
            { 
                return SR.UnsupportedMemberExpressionWithType(memberExpressionBody.Member.GetType().Name);
            } 
        }

        static string TryConvertReferenceMemberExpression(MemberExpression memberExpressionBody, Type operandType, bool throwOnError, out Activity> result)
        { 
            try
            { 
                MethodInfo specializedHandle = TryConvertReferenceMemberExpressionHandle.MakeGenericMethod(operandType, typeof(TResult)); 
                object[] parameters = new object[] { memberExpressionBody, throwOnError, null };
                string errorString = specializedHandle.Invoke(null, parameters) as string; 
                result = parameters[2] as Activity>;
                return errorString;
            }
            catch (TargetInvocationException e) 
            {
                throw FxTrace.Exception.AsError(e.InnerException); 
            } 
        }
 
        static string TryConvertReferenceMemberExpressionWorker(MemberExpression memberExpressionBody, bool throwOnError, out Activity> result)
        {
            result = null;
            Activity operand = null; 
            Activity> operandReference = null;
            bool isValueType = typeof(TOperand).IsValueType; 
            if (memberExpressionBody.Expression != null) 
            {
                // Static property might not have any expressions. 
                if (!isValueType)
                {
                    string operandError = TryConvert(memberExpressionBody.Expression, throwOnError, out operand);
                    if (operandError != null) 
                    {
                        return operandError; 
                    } 
                }
                else 
                {
                    string operandError = TryConvertReference(memberExpressionBody.Expression, throwOnError, out operandReference);
                    if (operandError != null)
                    { 
                        return operandError;
                    } 
                } 
            }
            if (memberExpressionBody.Member is PropertyInfo) 
            {
                if (!isValueType)
                {
                    if (operand == null) 
                    {
                        result = new PropertyReference { PropertyName = memberExpressionBody.Member.Name }; 
                    } 
                    else
                    { 
                        result = new PropertyReference { Operand = operand, PropertyName = memberExpressionBody.Member.Name };
                    }
                }
                else 
                {
                    if (operandReference == null) 
                    { 
                        result = new ValueTypePropertyReference { PropertyName = memberExpressionBody.Member.Name };
                    } 
                    else
                    {
                        result = new ValueTypePropertyReference { OperandLocation = operandReference, PropertyName = memberExpressionBody.Member.Name };
                    } 

                } 
                return null; 
            }
            if (memberExpressionBody.Member is FieldInfo) 
            {
                if (!isValueType)
                {
                    if (operand == null) 
                    {
                        result = new FieldReference { FieldName = memberExpressionBody.Member.Name }; 
                    } 
                    else
                    { 
                        result = new FieldReference { Operand = operand, FieldName = memberExpressionBody.Member.Name };
                    }
                }
                else 
                {
                    if (operandReference == null) 
                    { 
                        result = new ValueTypeFieldReference { FieldName = memberExpressionBody.Member.Name };
                    } 
                    else
                    {
                        result = new ValueTypeFieldReference { OperandLocation = operandReference, FieldName = memberExpressionBody.Member.Name };
                    } 

                } 
                return null; 
            }
            if (throwOnError) 
            {
                throw FxTrace.Exception.AsError(new NotSupportedException(SR.UnsupportedMemberExpressionWithType(memberExpressionBody.Member.GetType().Name)));
            }
            else 
            {
                return SR.UnsupportedMemberExpressionWithType(memberExpressionBody.Member.GetType().Name); 
            } 
        }
 
        static string TryConvertOverloadingUnaryOperator(UnaryExpression unaryExpression, Activity operand, bool throwOnError, out Activity result)
        {
            result = null;
            if (!unaryExpression.Method.IsStatic) 
            {
                if (throwOnError) 
                { 
                    throw FxTrace.Exception.AsError(new ValidationException(SR.OverloadingMethodMustBeStatic));
                } 
                else
                {
                    return SR.OverloadingMethodMustBeStatic;
                } 
            }
 
            result = new InvokeMethod 
            {
                MethodName = unaryExpression.Method.Name, 
                TargetType = unaryExpression.Method.DeclaringType,
                Parameters = {new InArgument { Expression = operand}},
            };
            return null; 
        }
 
        static string TryConvertOverloadingBinaryOperator(BinaryExpression binaryExpression, Activity left, Activity right, bool throwOnError, out Activity result) 
        {
            result = null; 
            if (!binaryExpression.Method.IsStatic)
            {
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(new ValidationException(SR.OverloadingMethodMustBeStatic));
                } 
                else 
                {
                    return SR.OverloadingMethodMustBeStatic; 
                }
            }

            result = new InvokeMethod 
            {
                MethodName = binaryExpression.Method.Name, 
                TargetType = binaryExpression.Method.DeclaringType, 
                Parameters = {new InArgument{Expression = left, EvaluationOrder = 0}, new InArgument{Expression = right, EvaluationOrder = 1}},
            }; 
            return null;
        }

        static string TryConvertMethodCallExpression(MethodCallExpression methodCallExpression, bool throwOnError, out Activity result) 
        {
            result = null; 
            MethodInfo methodInfo = methodCallExpression.Method; 

            if (methodInfo == null) 
            {
                if (throwOnError)
                {
                    throw FxTrace.Exception.AsError(new ValidationException(SR.MethodInfoRequired(methodCallExpression.GetType().Name))); 
                }
                else 
                { 
                    return SR.MethodInfoRequired(methodCallExpression.GetType().Name);
                } 
            };
            if (string.IsNullOrEmpty(methodInfo.Name) || methodInfo.DeclaringType == null)
            {
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(new ValidationException(SR.MethodNameRequired(methodInfo.GetType().Name))); 
                } 
                else
                { 
                    return SR.MethodNameRequired(methodInfo.GetType().Name);
                }
            }
            InvokeMethod invokeMethod = new InvokeMethod 
            {
                MethodName = methodInfo.Name, 
            }; 

            ParameterInfo[] parameterInfoArray = methodInfo.GetParameters(); 
            if (methodCallExpression.Arguments.Count != parameterInfoArray.Length)//no optional argument call for LINQ expression
            {
                if (throwOnError)
                { 
                    throw FxTrace.Exception.AsError(new ValidationException(SR.ArgumentNumberRequiresTheSameAsParameterNumber(methodCallExpression.GetType().Name)));
                } 
                else 
                {
                    return SR.ArgumentNumberRequiresTheSameAsParameterNumber(methodCallExpression.GetType().Name); 
                }
            }

            string error = TryConvertArguments(methodCallExpression.Arguments, invokeMethod.Parameters, methodCallExpression.GetType(), 1, parameterInfoArray, throwOnError); 
            if (error != null)
            { 
                return error; 
            }
 
            foreach (Type type in methodInfo.GetGenericArguments())
            {
                if (type == null)
                { 
                    if (throwOnError)
                    { 
                        throw FxTrace.Exception.AsError(new ValidationException(SR.InvalidGenericTypeInfo(methodCallExpression.GetType().Name))); 
                    }
                    else 
                    {
                        return SR.InvalidGenericTypeInfo(methodCallExpression.GetType().Name);
                    }
                } 
                invokeMethod.GenericTypeArguments.Add(type);
            } 
            if (methodInfo.IsStatic) 
            {
                invokeMethod.TargetType = methodInfo.DeclaringType; 
            }
            else
            {
                if (methodCallExpression.Object == null) 
                {
                    if (throwOnError) 
                    { 
                        throw FxTrace.Exception.AsError(new ValidationException(SR.InstanceMethodCallRequiresTargetObject));
                    } 
                    else
                    {
                        return SR.InstanceMethodCallRequiresTargetObject;
                    } 
                }
                object[] parameters = new object[] { methodCallExpression.Object, false, throwOnError, null }; 
                error = TryConvertArgumentExpressionHandle.MakeGenericMethod(methodCallExpression.Object.Type).Invoke(null, parameters) as string; 
                if (error != null)
                { 
                    return error;
                }
                InArgument argument = (InArgument)parameters[3];
                argument.EvaluationOrder = 0; 
                invokeMethod.TargetObject = argument;
            } 
            result = invokeMethod; 
            return null;
        } 

        static string TryConvertInvocationExpression(InvocationExpression invocationExpression, bool throwOnError, out Activity result)
        {
            result = null; 
            if (invocationExpression.Expression == null || invocationExpression.Expression.Type == null)
            { 
                if (throwOnError) 
                {
                    throw FxTrace.Exception.AsError(new ValidationException(SR.InvalidExpressionProperty(invocationExpression.GetType().Name))); 
                }
                else
                {
                    return SR.InvalidExpressionProperty(invocationExpression.GetType().Name); 
                }
            } 
            InvokeMethod invokeMethod = new InvokeMethod 
            {
                MethodName = "Invoke", 
            };
            object[] parameters = new object[] { invocationExpression.Expression, false, throwOnError, null };
            string error = TryConvertArgumentExpressionHandle.MakeGenericMethod(invocationExpression.Expression.Type).Invoke(null, parameters) as string;
            if (error != null) 
            {
                return error; 
            } 
            InArgument argument = (InArgument)parameters[3];
            argument.EvaluationOrder = 0; 
            invokeMethod.TargetObject = argument;

            //InvocationExpression can not have a by-ref parameter.
            error = TryConvertArguments(invocationExpression.Arguments, invokeMethod.Parameters, invocationExpression.GetType(), 1, null, throwOnError); 

            if (error != null) 
            { 
                return error;
            } 

            result = invokeMethod;
            return null;
        } 

        static string TryConvertArgumentExpressionWorker(Expression expression, bool isByRef, bool throwOnError, out System.Activities.Argument result) 
        { 
            result = null;
 
            string error = null;

            if (isByRef)
            { 
                Activity> argument;
                error = TryConvertReference(expression, throwOnError, out argument); 
                if (error == null) 
                {
                    result = new InOutArgument 
                   {
                       Expression = argument,
                   };
                } 
            }
            else 
            { 
                Activity argument;
                error = TryConvert(expression, throwOnError, out argument); 
                if (error == null)
                {
                    result = new InArgument
                    { 
                        Expression = argument,
                    }; 
                } 
            }
            return error; 
        }

        static string TryConvertNewExpression(NewExpression newExpression, bool throwOnError, out Activity result)
        { 
            result = null;
            New newActivity = new New(); 
            ParameterInfo[] parameterInfoArray = null; 
            if (newExpression.Constructor != null)
            { 
                parameterInfoArray = newExpression.Constructor.GetParameters();
                if (newExpression.Arguments.Count != parameterInfoArray.Length)//no optional argument call for LINQ expression
                {
                    if (throwOnError) 
                    {
                        throw FxTrace.Exception.AsError(new ValidationException(SR.ArgumentNumberRequiresTheSameAsParameterNumber(newExpression.GetType().Name))); 
                    } 
                    else
                    { 
                        return SR.ArgumentNumberRequiresTheSameAsParameterNumber(newExpression.GetType().Name);
                    }
                }
            } 

            string error = TryConvertArguments(newExpression.Arguments, newActivity.Arguments, newExpression.GetType(), 0, parameterInfoArray, throwOnError); 
            if (error != null) 
            {
                return error; 
            }
            result = newActivity;
            return null;
        } 

        static string TryConvertNewArrayExpression(NewArrayExpression newArrayExpression, bool throwOnError, out Activity result) 
        { 
            result = null;
            NewArray newArrayActivity = new NewArray(); 
            string error = TryConvertArguments(newArrayExpression.Expressions, newArrayActivity.Bounds, newArrayExpression.GetType(), 0, null, throwOnError);
            if (error != null)
            {
                return error; 
            }
            result = newArrayActivity; 
            return null; 

        } 

        static string TryConvertArguments(ReadOnlyCollection source, IList target, Type expressionType, int baseEvaluationOrder, ParameterInfo[] parameterInfoArray, bool throwOnError)
        {
            object[] parameters; 
            for (int i = 0; i < source.Count; i++)
            { 
                bool isByRef = false; 
                Expression expression = source[i];
                if (parameterInfoArray != null) 
                {
                    ParameterInfo parameterInfo = parameterInfoArray[i];

                    if (parameterInfo == null || parameterInfo.ParameterType == null) 
                    {
                        if (throwOnError) 
                        { 
                            throw FxTrace.Exception.AsError(new ValidationException(SR.InvalidParameterInfo(i, expressionType.Name)));
                        } 
                        else
                        {
                            return SR.InvalidParameterInfo(i, expressionType.Name);
                        } 
                    }
                    isByRef = parameterInfo.ParameterType.IsByRef; 
                } 
                parameters = new object[] { expression, isByRef, throwOnError, null };
                string error = TryConvertArgumentExpressionHandle.MakeGenericMethod(expression.Type).Invoke(null, parameters) as string; 
                if (error != null)
                {
                    return error;
                } 
                Argument argument = (Argument) parameters[3];
                argument.EvaluationOrder = i + baseEvaluationOrder; 
                target.Add(argument); 
            }
            return null; 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK