Ejemplo n.º 1
0
        _ParamInfo[] _GetParamInfos(CodeExpressionCollection parms, CodeDomResolverScope scope = null)
        {
            var result = new _ParamInfo[parms.Count];

            for (var i = 0; i < result.Length; i++)
            {
                CodeExpression e = parms[i];
                _ParamInfo     p = default(_ParamInfo);
                p.IsOptional = false;
                p.IsRetval   = false;
                var de = e as CodeDirectionExpression;
                if (null != de)
                {
                    switch (de.Direction)
                    {
                    case FieldDirection.In:
                        break;

                    case FieldDirection.Out:
                        p.IsOut = true;
                        break;

                    case FieldDirection.Ref:
                        p.IsIn = p.IsOut = true;
                        break;
                    }
                    e = de.Expression;
                }
                p.ParameterType = _resolver.GetTypeOfExpression(e, _scope);
                result[i]       = p;
            }
            return(result);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Attempts to return the type of the specified expression using the specified scope
 /// </summary>
 /// <param name="expr">The expression to evaluate</param>
 /// <param name="scope">The scope to use, or null to use the expression's current scope</param>
 /// <returns>A <see cref="CodeTypeReference"/> representing the type of the expression or null if it could not be retrieved</returns>
 public CodeTypeReference TryGetTypeOfExpression(CodeExpression expr, CodeDomResolverScope scope = null)
 {
     // reimplementing a try version of this is a lot of code, and frankly, the resolution takes so much
     // longer than any exception handling that this is acceptable in this case.
     try
     {
         return(GetTypeOfExpression(expr, scope));
     }
     catch (Exception) { return(null); }
 }
        Type _EvalType(CodeTypeReference r, CodeDomResolverScope s)
        {
            if (null == s)
            {
                s = GetScope(r);
            }
            var t = _ResolveType(r, s);

            if (null == t)
            {
                throw new TypeLoadException("The type could not be resolved");
            }
            var result = t as Type;

            if (null == result)
            {
                throw new NotSupportedException("Only runtime types may be evaluated");
            }
            return(result);
        }
Ejemplo n.º 4
0
        _ParamInfo[] _GetParamInfos(CodeParameterDeclarationExpressionCollection parms, CodeDomResolverScope scope = null)
        {
            var result = new _ParamInfo[parms.Count];

            for (var i = 0; i < result.Length; i++)
            {
                _ParamInfo p = default(_ParamInfo);
                p.IsOptional   = false;
                p.IsRetval     = false;
                p.Name         = parms[i].Name;
                p.DefaultValue = DBNull.Value;
                var pd = parms[i];
                switch (pd.Direction)
                {
                case FieldDirection.In:
                    break;

                case FieldDirection.Out:
                    p.IsOut = true;
                    break;

                case FieldDirection.Ref:
                    p.IsIn = p.IsOut = true;
                    break;
                }
                p.ParameterType = pd.Type;
                if (null != scope)
                {
                    p.ParameterType = _resolver.GetQualifiedType(pd.Type, scope);
                }
                result[i] = p;
            }
            return(result);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Initializes the binder with the given scope
 /// </summary>
 /// <param name="scope">The scope in which the binder is to operate</param>
 public CodeDomBinder(CodeDomResolverScope scope)
 {
     _resolver = scope.Resolver;
     _scope    = scope;
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets the type of the specified expression, at the optional given scope
        /// </summary>
        /// <param name="expr">The expression to evaluate</param>
        /// <param name="scope">The scope at which evaluation occurs, or null to use the expression's scope</param>
        /// <returns>A <see cref="CodeTypeReference"/> representing the type of the expression</returns>
        public CodeTypeReference GetTypeOfExpression(CodeExpression expr, CodeDomResolverScope scope = null)
        {
            if (null == expr)
            {
                throw new ArgumentNullException(nameof(expr));
            }
            // first let's do the easy ones.
            var cpe = expr as CodePrimitiveExpression;

            if (null != cpe)
            {
                if (null == cpe.Value)
                {
                    return(new CodeTypeReference(typeof(void)));
                }
                return(new CodeTypeReference(cpe.Value.GetType()));
            }
            var cbe = expr as CodeBinaryOperatorExpression;

            if (null != cbe)
            {
                switch (cbe.Operator)
                {
                case CodeBinaryOperatorType.BooleanAnd:
                case CodeBinaryOperatorType.BooleanOr:
                case CodeBinaryOperatorType.GreaterThan:
                case CodeBinaryOperatorType.GreaterThanOrEqual:
                case CodeBinaryOperatorType.IdentityEquality:
                case CodeBinaryOperatorType.IdentityInequality:
                case CodeBinaryOperatorType.LessThan:
                case CodeBinaryOperatorType.LessThanOrEqual:
                case CodeBinaryOperatorType.ValueEquality:
                    return(new CodeTypeReference(typeof(bool)));

                case CodeBinaryOperatorType.Assign:
                case CodeBinaryOperatorType.Add:
                case CodeBinaryOperatorType.Subtract:
                case CodeBinaryOperatorType.Multiply:
                case CodeBinaryOperatorType.Divide:
                case CodeBinaryOperatorType.Modulus:
                case CodeBinaryOperatorType.BitwiseAnd:
                case CodeBinaryOperatorType.BitwiseOr:
                    return(_PromoteType(GetTypeOfExpression(cbe.Left), GetTypeOfExpression(cbe.Right)));
                }
            }
            var tr = expr as CodeTypeReferenceExpression;

            if (null != tr)
            {
                if (null == tr.Type)
                {
                    throw new InvalidOperationException("The type reference expression had no target object");
                }
                return(tr.Type);
            }
            var pd = expr as CodeParameterDeclarationExpression;

            if (null != pd)
            {
                if (null == pd.Type)
                {
                    throw new InvalidOperationException("The parameter declaration had no target object");
                }
                return(pd.Type);
            }
            var oc = expr as CodeObjectCreateExpression;

            if (null != oc)
            {
                if (null == oc.CreateType)
                {
                    throw new InvalidOperationException("The object creation expression had no create type");
                }
                return(oc.CreateType);
            }
            var ac = expr as CodeArrayCreateExpression;

            if (null != ac)
            {
                if (null == ac.CreateType)
                {
                    throw new InvalidOperationException("The array creation expression had no create type");
                }
                var ctr = new CodeTypeReference();
                ctr.ArrayElementType = ac.CreateType.ArrayElementType;
                ctr.ArrayRank        = ac.CreateType.ArrayRank;
                ctr.BaseType         = ac.CreateType.BaseType;
                ctr.TypeArguments.AddRange(ac.CreateType.TypeArguments);
                return(ctr);
            }
            var dc = expr as CodeDelegateCreateExpression;

            if (null != dc)
            {
                if (null == dc.DelegateType)
                {
                    throw new InvalidOperationException("The delegate creation expression had no delegate type");
                }
                return(dc.DelegateType);
            }
            var dv = expr as CodeDefaultValueExpression;

            if (null != dv)
            {
                if (null == dv.Type)
                {
                    throw new InvalidOperationException("The default value expression had no type");
                }
                return(dv.Type);
            }
            var dire = expr as CodeDirectionExpression;

            if (null != dire)
            {
                if (null == dire.Expression)
                {
                    throw new InvalidOperationException("The direction expression had no target expression");
                }
                return(GetTypeOfExpression(dire.Expression, scope));
            }
            var ai = expr as CodeArrayIndexerExpression;

            if (null != ai)
            {
                var aet = GetTypeOfExpression(ai.TargetObject).ArrayElementType;
                if (null == aet)
                {
                    throw new InvalidOperationException("The associated array type's array element type was null");
                }
                return(aet);
            }
            var cst = expr as CodeCastExpression;

            if (null != cst)
            {
                if (null == cst.TargetType)
                {
                    throw new InvalidOperationException("The cast expression's target type was null");
                }
                return(cst.TargetType);
            }
            var to = expr as CodeTypeOfExpression;

            if (null != to)
            {
                return(new CodeTypeReference(typeof(Type)));
            }
            // now things get complicated
            if (null == scope)
            {
                scope = GetScope(expr);
            }
            var cmi = expr as CodeMethodInvokeExpression;

            if (null != cmi)
            {
                var types = new CodeTypeReference[cmi.Parameters.Count];
                for (var i = 0; i < types.Length; ++i)
                {
                    var p  = cmi.Parameters[i];
                    var de = p as CodeDirectionExpression;
                    if (null != de)
                    {
                        p = de.Expression;
                    }
                    types[i] = GetTypeOfExpression(p, scope);
                    if (null == types[i])
                    {
                        throw new InvalidOperationException(string.Format("Could not resolve parameter index {0} of method invoke expression", i));
                    }
                }
                var mr = cmi.Method;
                var t  = GetTypeOfExpression(mr.TargetObject, scope);
                var rt = TryResolveType(t, scope);
                if (null == rt)
                {
                    throw new InvalidOperationException("Could not resolve the type of the target expression of the method invoke expression");
                }
                var    rtt    = rt as Type;
                object tm     = null;
                var    binder = new CodeDomBinder(scope);
                var    grp    = binder.GetMethodGroup(rt, mr.MethodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

                //tm =binder.BindToMethod(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, grp,types, null,null,null,out state);
                tm = binder.SelectMethod(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, grp, types, null);
                if (null == tm)
                {
                    throw new InvalidOperationException("Unable to find a suitable method to bind to in method invoke expression");
                }
                var mi = tm as MethodInfo;
                if (null != mi)
                {
                    return(new CodeTypeReference(mi.ReturnType));
                }
                var cm = tm as CodeMemberMethod;
                if (null == cm.ReturnType)
                {
                    return(new CodeTypeReference(typeof(void)));
                }
                return(cm.ReturnType);
            }
            var ar = expr as CodeArgumentReferenceExpression;

            if (null != ar)
            {
                var t = scope.ArgumentTypes[ar.ParameterName];
                if (null == t)
                {
                    throw new InvalidOperationException("The argument's type was null");
                }
                return(t);
            }

            var vr = expr as CodeVariableReferenceExpression;

            if (null != vr)
            {
                var t = scope.VariableTypes[vr.VariableName];
                if (null == t)
                {
                    throw new InvalidOperationException("The variable's type was null. This could be due to an unresolved var declaration in Slang");
                }
                return(t);
            }
            var br = expr as CodeBaseReferenceExpression;

            if (null != br)
            {
                var dt = scope.DeclaringType;
                if (null != dt)
                {
                    if (0 < dt.BaseTypes.Count)
                    {                       // this isn't exactly right. See notes below
                        var bt = dt.BaseTypes[0];
                        if (null == bt)
                        {
                            throw new InvalidOperationException("The declaring type's base types contained a null entry.");
                        }
                        return(bt);
                    }
                    else if (dt.IsClass || dt.IsInterface)
                    {
                        return(new CodeTypeReference(typeof(object)));
                    }
                    else if (dt.IsEnum)
                    {
                        return(new CodeTypeReference(typeof(Enum)));
                    }
                    else if (dt.IsStruct)
                    {
                        return(new CodeTypeReference(typeof(ValueType)));
                    }
                    else
                    {
                        throw new InvalidOperationException("The declaring type is not a class, interface, enum or struct");
                    }
                }
                throw new InvalidOperationException("There is no declarting type in the scope from which to retrieve a base reference");
            }
            var th = expr as CodeThisReferenceExpression;

            if (null != th)
            {
                var dt = scope.DeclaringType;
                if (null != dt)
                {
                    // TODO: We have no way to fully resolve this because we'd need to know
                    // what expression created this object. If it's a template we can't know
                    // what the template args are. The best we can return is something like
                    // Foo<> so we do that. This is hateful but I don't know what else to do
                    // here
                    return(new CodeTypeReference(_GetBaseNameOfType(dt, scope)));
                }
                throw new InvalidOperationException("There was no declaring type in the scope from which to retrieve a this reference");
            }
            var fr = expr as CodeFieldReferenceExpression;

            if (null != fr)
            {
                var t  = GetTypeOfExpression(fr.TargetObject, scope);
                var tt = _ResolveType(t, scope);
                if (null == tt)
                {
                    throw new InvalidOperationException("The field reference's target expression type could not be resolved");
                }
                var binder   = new CodeDomBinder(scope);
                var fl       = BindingFlags.Public | BindingFlags.NonPublic;
                var isStatic = (fr.TargetObject as CodeTypeReferenceExpression) != null;
                if (isStatic)
                {
                    fl |= BindingFlags.Static;
                }
                else
                {
                    fl |= BindingFlags.Instance;
                }
                var res = binder.GetField(tt, fr.FieldName, fl);
                if (null != res)
                {
                    var mi = res as MemberInfo;
                    if (null != mi)
                    {
                        return(GetTypeForMember(mi));
                    }
                    return(GetTypeForMember(res as CodeTypeMember));
                }
                throw new InvalidOperationException("A matching field could not be found");
            }
            var pr = expr as CodePropertyReferenceExpression;

            if (null != pr)
            {
                var t  = GetTypeOfExpression(pr.TargetObject, scope);
                var tt = _ResolveType(t, scope);
                if (null == tt)
                {
                    throw new InvalidOperationException("The property reference's target expression type could not be resolved");
                }
                var binder   = new CodeDomBinder(scope);
                var fl       = BindingFlags.Public | BindingFlags.NonPublic;
                var isStatic = (pr.TargetObject as CodeTypeReferenceExpression) != null;
                if (isStatic)
                {
                    fl |= BindingFlags.Static;
                }
                else
                {
                    fl |= BindingFlags.Instance;
                }
                var res = binder.GetPropertyGroup(tt, pr.PropertyName, fl);
                if (0 < res.Length)
                {
                    var mi = res[0] as MemberInfo;
                    if (null != mi)
                    {
                        return(GetTypeForMember(mi));
                    }
                    return(GetTypeForMember(res[0] as CodeTypeMember));
                }
                throw new InvalidOperationException("A matching property could not be found");
            }
            var er = expr as CodeEventReferenceExpression;

            if (null != er)
            {
                var t  = GetTypeOfExpression(er.TargetObject, scope);
                var tt = _ResolveType(t, scope);
                if (null == tt)
                {
                    throw new InvalidOperationException("The event reference's target expression type could not be resolved");
                }
                var binder   = new CodeDomBinder(scope);
                var fl       = BindingFlags.Public | BindingFlags.NonPublic;
                var isStatic = (er.TargetObject as CodeTypeReferenceExpression) != null;
                if (isStatic)
                {
                    fl |= BindingFlags.Static;
                }
                else
                {
                    fl |= BindingFlags.Instance;
                }
                var res = binder.GetEvent(tt, er.EventName, fl);
                if (null != res)
                {
                    var mi = res as MemberInfo;
                    if (null != mi)
                    {
                        return(GetTypeForMember(mi));
                    }
                    else
                    {
                        return(GetTypeForMember(res as CodeTypeMember));
                    }
                }
                throw new InvalidOperationException("A matching event could not be found");
            }

            var di = expr as CodeDelegateInvokeExpression;

            if (null != di)
            {
                var ctr = GetTypeOfExpression(di.TargetObject, scope);

                var tt = _ResolveType(ctr, scope) as Type;
                if (null == tt)
                {
                    throw new InvalidOperationException("The delegate invoke expression's target expression type could not resolved.");
                }
                var ma = tt.GetMember("Invoke");
                if (0 < ma.Length)
                {
                    var mi = ma[0] as MethodInfo;
                    if (null != mi)
                    {
                        return(new CodeTypeReference(mi.ReturnType));
                    }
                }
                throw new InvalidOperationException("The target is not a delegate");
            }
            var ie = expr as CodeIndexerExpression;

            if (null != ie)
            {
                var t     = GetTypeOfExpression(ie.TargetObject, scope);
                var types = new CodeTypeReference[ie.Indices.Count];
                for (var i = 0; i < types.Length; ++i)
                {
                    var p  = ie.Indices[i];
                    var de = p as CodeDirectionExpression;
                    if (null != de)
                    {
                        p = de.Expression;
                    }
                    types[i] = GetTypeOfExpression(p, scope);
                    if (IsNullOrVoidType(types[i]))
                    {
                        throw new InvalidOperationException("One or more of the indexer argument types was void");
                    }
                }
                var tt = TryResolveType(t, scope);
                if (null == tt)
                {
                    throw new InvalidOperationException("The indexer expression's target expression type could not be resolved");
                }
                var    binder = new CodeDomBinder(scope);
                var    td     = tt as CodeTypeDeclaration;
                object tm     = null;
                if (null != td)
                {
                    var grp = binder.GetPropertyGroup(td, "Item", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
                    tm = binder.SelectProperty(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance, grp, null, types, null);
                }
                else
                {
                    var rt = tt as Type;
                    if (null != rt)
                    {
                        var grp = binder.GetPropertyGroup(rt, "Item", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
                        tm = binder.SelectProperty(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance, grp, null, types, null);
                    }
                }
                if (null == tm)
                {
                    throw new InvalidOperationException("The indexer expression's target object type does not have a matching indexer property");
                }
                var pi = tm as PropertyInfo;
                if (null != pi)
                {
                    return(new CodeTypeReference(pi.PropertyType));
                }
                var cm = tm as CodeMemberProperty;
                if (null == cm.Type)
                {
                    throw new InvalidOperationException("The property declaration's property type was null");
                }
                return(cm.Type);
            }
            throw new InvalidOperationException(string.Format("Unsupported expression type {0}", expr.GetType().Name));
        }
        object _EvalBinOp(CodeBinaryOperatorExpression bo, CodeDomResolverScope s)
        {
            if (null == s)
            {
                s = GetScope(bo);
            }
            switch (bo.Operator)
            {
            case CodeBinaryOperatorType.Add:
                return(_Add(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.Subtract:
                return(_Subtract(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.Multiply:
                return(_Multiply(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.Divide:
                return(_Divide(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.Modulus:
                return(_Modulo(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.Assign:
                throw new NotSupportedException("Evaluate cannot change state.");

            case CodeBinaryOperatorType.BitwiseAnd:
                return(_BitwiseAnd(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.BitwiseOr:
                return(_BitwiseOr(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.BooleanAnd:
                return(((bool)_Eval(bo.Left, s)) && ((bool)_Eval(bo.Right, s)));

            case CodeBinaryOperatorType.BooleanOr:
                return(((bool)_Eval(bo.Left, s)) || ((bool)_Eval(bo.Right, s)));

            case CodeBinaryOperatorType.LessThan:
                return(_LessThan(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.LessThanOrEqual:
                return(_LessThanOrEqual(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.GreaterThan:
                return(_GreaterThan(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.GreaterThanOrEqual:
                return(_GreaterThanOrEqual(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.IdentityEquality:
            case CodeBinaryOperatorType.ValueEquality:
                return(_Equals(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            case CodeBinaryOperatorType.IdentityInequality:
                return(_NotEqual(_Eval(bo.Left, s), _Eval(bo.Right, s)));

            default:
                throw new NotSupportedException("The specified operation is not supported.");
            }
        }
        object _Eval(CodeExpression e, CodeDomResolverScope s)
        {
            var ac = e as CodeArrayCreateExpression;

            if (null != ac)
            {
                if (null == s)
                {
                    s = GetScope(ac);
                }
                var type = _EvalType(ac.CreateType, s);
                var len  = ac.Initializers.Count;
                if (0 == len)
                {
                    if (0 < ac.Size)
                    {
                        len = ac.Size;
                    }
                    else
                    {
                        len = (int)_Eval(ac.SizeExpression, s);
                    }
                }
                var arr = Array.CreateInstance(type, len);
                if (0 < ac.Initializers.Count)
                {
                    for (int ic = ac.Initializers.Count, i = 0; i < ic; ++i)
                    {
                        arr.SetValue(_Eval(ac.Initializers[i], s), i);
                    }
                }
            }
            var ai = e as CodeArrayIndexerExpression;

            if (null != ai)
            {
                if (null == s)
                {
                    s = GetScope(e);
                }
                var arr = (Array)_Eval(ai.TargetObject, s);
                var ind = new int[ai.Indices.Count];
                for (var i = 0; i < ind.Length; i++)
                {
                    ind[i] = (int)_Eval(ai.Indices[i], s);
                }
                return(arr.GetValue(ind));
            }
            var bo = e as CodeBinaryOperatorExpression;

            if (null != bo)
            {
                return(_EvalBinOp(bo, s));
            }
            var c = e as CodeCastExpression;

            if (null != c)
            {
                if (null == s)
                {
                    s = GetScope(c);
                }
                var type = _EvalType(c.TargetType, s);
                var rhs  = _Eval(c.Expression, s);
                if (null == rhs)                 // cast from null allowed
                {
                    if (type.IsValueType)
                    {
                        throw new InvalidCastException("Cannot cast null to a value type");
                    }
                    return(null);
                }
                if (rhs.GetType().IsAssignableFrom(type))
                {
                    return(rhs);
                }
                throw new InvalidCastException("The value is not assignable to that target type");
            }
            var dv = e as CodeDefaultValueExpression;

            if (null != dv)
            {
                if (null == s)
                {
                    s = GetScope(c);
                }
                var type = _EvalType(c.TargetType, s);
                return(Activator.CreateInstance(type));
            }
            var dc = e as CodeDelegateCreateExpression;

            if (null != dc)
            {
                if (null == s)
                {
                    s = GetScope(dc);
                }
                var type = _EvalType(dc.DelegateType, s);
                var targ = _Eval(dc.TargetObject, s);
                var m    = targ.GetType().GetMethod(dc.MethodName, ((BindingFlags)(-1)) & ~BindingFlags.DeclaredOnly);
                return(Delegate.CreateDelegate(type, targ, m));
            }
            var di = e as CodeDelegateInvokeExpression;

            if (null != di)
            {
                if (null == s)
                {
                    s = GetScope(di);
                }
                var lhs   = _Eval(di.TargetObject, s);
                var parms = new object[di.Parameters.Count];
                for (var i = 0; i < parms.Length; i++)
                {
                    parms[i] = _Eval(di.Parameters[i], s);
                }

                var m = lhs.GetType().GetMethod("Invoke");
                try
                {
                    return(m.Invoke(lhs, parms));
                }
                catch (TargetInvocationException tex)
                {
                    throw tex.InnerException;
                }
            }
            var de = e as CodeDirectionExpression;

            if (null != de)
            {
                if (null == s)
                {
                    s = GetScope(de);
                }
                return(_Eval(de.Expression, s));
            }
            var er = e as CodeEventReferenceExpression;

            if (null != er)
            {
                if (null == s)
                {
                    s = GetScope(er);
                }
                var ev = _Eval(er.TargetObject, s);
                var ei = ev.GetType().GetEvent(er.EventName);
                // i have no idea what else to return. A delegate?
                return(new KeyValuePair <EventInfo, object>(ei, ev));
            }
            var fr = e as CodeFieldReferenceExpression;

            if (null != fr)
            {
                if (null == s)
                {
                    s = GetScope(fr);
                }
                var trr  = _Eval(fr.TargetObject, s);
                var type = trr as Type;
                if (null != type)
                {
                    return(type.GetField(fr.FieldName).GetValue(null));
                }
                return(trr.GetType().GetField(fr.FieldName).GetValue(trr));
            }
            var ix = e as CodeIndexerExpression;

            if (null != ix)
            {
                if (null == s)
                {
                    s = GetScope(ix);
                }
                var ir   = _Eval(ix.TargetObject, s);
                var pia  = _GetParamInfos(ix.Indices, s);
                var tt   = ir as Type;
                var type = null != tt ? tt : ir.GetType();
                try
                {
                    if (null == tt)
                    {
                        return(type.InvokeMember("Item", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.InvokeMethod | BindingFlags.Instance, null, ir, _GetParamValues(pia)));
                    }
                    return(type.InvokeMember("Item", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.FlattenHierarchy, null, null, _GetParamValues(pia)));
                }
                catch (TargetInvocationException tex)
                {
                    throw tex.InnerException;
                }
            }
            var mi = e as CodeMethodInvokeExpression;

            if (null != mi)
            {
                if (null == s)
                {
                    s = GetScope(mi);
                }
                var mv   = _Eval(mi.Method.TargetObject, s);
                var type = mv.GetType();
                var tt   = mv as Type;
                if (null != tt)
                {
                    type = tt;
                }

                var pia = _GetParamInfos(mi.Parameters, s);
                try
                {
                    if (null == tt)
                    {
                        return(type.InvokeMember(mi.Method.MethodName, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, mv, _GetParamValues(pia)));
                    }
                    return(type.InvokeMember(mi.Method.MethodName, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.FlattenHierarchy, null, null, _GetParamValues(pia)));
                }
                catch (TargetInvocationException tex)
                {
                    throw tex.InnerException;
                }
            }
            var mr = e as CodeMethodReferenceExpression;

            if (null != mr)
            {
                if (null == s)
                {
                    s = GetScope(mr);
                }
                var mv = _Eval(mr.TargetObject, s);
                var ml = new List <MethodInfo>();
                var ma = mv.GetType().GetMethods();
                for (var i = 0; i < ma.Length; ++i)
                {
                    var m = ma[i];
                    if (0 == string.Compare(m.Name, mr.MethodName, StringComparison.InvariantCulture))
                    {
                        ml.Add(m);
                    }
                }
                return(new KeyValuePair <MethodInfo[], object>(ml.ToArray(), mv));               // basically returning a "MethodGroup" with an attached target object. stupid but what can we do?
            }
            var oc = e as CodeObjectCreateExpression;

            if (null != oc)
            {
                if (null == s)
                {
                    s = GetScope(oc);
                }
                var t   = _EvalType(oc.CreateType, s);
                var pia = _GetParamInfos(oc.Parameters, s);
                return(Activator.CreateInstance(t, _GetParamValues(pia)));
            }
            var p = e as CodePrimitiveExpression;

            if (null != p)
            {
                return(p.Value);
            }
            var pr = e as CodePropertyReferenceExpression;

            if (null != pr)
            {
                if (null == s)
                {
                    s = GetScope(pr);
                }
                var trr  = _Eval(pr.TargetObject, s);
                var type = trr as Type;
                if (null != type)
                {
                    return(type.GetProperty(pr.PropertyName).GetValue(null));
                }
                return(trr.GetType().GetProperty(pr.PropertyName).GetValue(trr));
            }
            var to = e as CodeTypeOfExpression;

            if (null != to)
            {
                if (null == s)
                {
                    s = GetScope(to);
                }
                return(_EvalType(to.Type, s));
            }
            var tr = e as CodeTypeReferenceExpression;

            if (null != tr)
            {
                return(_EvalType(tr.Type, s));
            }
            throw new NotSupportedException(string.Format("Unable to evaluate expressions of type {0}", e.GetType().FullName));
        }
 /// <summary>
 /// Evaluates the expression at the the given scope
 /// </summary>
 /// <param name="expression">The expression to evaluate</param>
 /// <param name="scope">The scope at which evaluation occurs or null to use the expression's scope</param>
 /// <returns>The result of the evaluation</returns>
 public object Evaluate(CodeExpression expression, CodeDomResolverScope scope = null)
 => _Eval(expression, scope);