public void TestFixtureSetUp()
        {
            datumConverterFactory = Substitute.For<IDatumConverterFactory>();

            var stringDatum = new Datum() {
                type = Datum.DatumType.R_STR,
                r_str = "Jackpot!",
            };

            var stringDatumConverter = Substitute.For<IDatumConverter<string>>();
            stringDatumConverter
                .ConvertObject("Jackpot!")
                .Returns(stringDatum);
            stringDatumConverter
                .ConvertDatum(Arg.Is<Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str))
                .Returns("Jackpot!");

            IDatumConverter<string> value;
            datumConverterFactory
                .TryGet<string>(datumConverterFactory, out value)
                .Returns(args => {
                        args[1] = stringDatumConverter;
                        return true;
                    });
            IDatumConverter value2;
            datumConverterFactory
                .TryGet(typeof(string), datumConverterFactory, out value2)
                .Returns(args => {
                        args[2] = stringDatumConverter;
                        return true;
                    });
        }
Exemple #2
0
        public void TestFixtureSetUp()
        {
            datumConverterFactory = Substitute.For <IDatumConverterFactory>();

            int[] ints = { 1, 2, 3 };

            var intDatumConverter = Substitute.For <IDatumConverter>();

            foreach (int i in ints)
            {
                var dtm = i.ToDatum();
                intDatumConverter
                .ConvertObject(i)
                .Returns(dtm);
                intDatumConverter
                .ConvertDatum(Arg.Is <Datum>(d => d.type == dtm.type && d.r_num == dtm.r_num))
                .Returns(i);
            }

            string[] strs = { "one", "two", "three" };

            var stringDatumConverter = Substitute.For <IDatumConverter>();

            foreach (var i in strs)
            {
                var dtm = i.ToDatum();
                stringDatumConverter
                .ConvertObject(i)
                .Returns(dtm);
                stringDatumConverter
                .ConvertDatum(Arg.Is <Datum>(d => d.type == dtm.type && d.r_str == dtm.r_str))
                .Returns(i);
            }

            IDatumConverter value;

            datumConverterFactory
            .TryGet(typeof(int), datumConverterFactory, out value)
            .Returns(args =>
            {
                args[2] = intDatumConverter;
                return(true);
            });
            datumConverterFactory
            .TryGet(typeof(string), datumConverterFactory, out value)
            .Returns(args =>
            {
                args[2] = stringDatumConverter;
                return(true);
            });
        }
        public void TestFixtureSetUp()
        {
            datumConverterFactory = Substitute.For<IDatumConverterFactory>();

            int[] ints = {1, 2, 3};
           
            var intDatumConverter = Substitute.For<IDatumConverter>();
            foreach(int i in ints)
            {
                var dtm = i.ToDatum();
                intDatumConverter
                    .ConvertObject(i)
                    .Returns(dtm);
                intDatumConverter
                    .ConvertDatum(Arg.Is<Datum>(d => d.type == dtm.type && d.r_num == dtm.r_num))
                    .Returns(i);
            }

            string[] strs = { "one", "two", "three" };

            var stringDatumConverter = Substitute.For<IDatumConverter>();
            foreach (var i in strs)
            {
                var dtm = i.ToDatum();
                stringDatumConverter
                    .ConvertObject(i)
                    .Returns(dtm);
                stringDatumConverter
                    .ConvertDatum(Arg.Is<Datum>(d => d.type == dtm.type && d.r_str == dtm.r_str))
                    .Returns(i);
            }

            IDatumConverter value;
            datumConverterFactory
                .TryGet(typeof(int), datumConverterFactory, out value)
                .Returns(args =>
                {
                    args[2] = intDatumConverter;
                    return true;
                });
            datumConverterFactory
                .TryGet(typeof(string), datumConverterFactory, out value)
                .Returns(args =>
                {
                    args[2] = stringDatumConverter;
                    return true;
                });
        }
            public static Tuple <bool, IDatumConverter> TryGet(IDatumConverterFactory target, IDatumConverterFactory rootDatumConverterFactory)
            {
                IDatumConverter <T> datumConverter;
                bool success = target.TryGet <T>(rootDatumConverterFactory, out datumConverter);

                return(new Tuple <bool, IDatumConverter>(success, datumConverter));
            }
Exemple #5
0
        public void TestFixtureSetUp()
        {
            datumConverterFactory = Substitute.For <IDatumConverterFactory>();
            queryConverter        = new QueryConverter(datumConverterFactory, expressionConverterFactory);

            var stringDatum = new Datum()
            {
                type  = Datum.DatumType.R_STR,
                r_str = "Jackpot!",
            };

            var stringDatumConverter = Substitute.For <IDatumConverter <string> >();

            stringDatumConverter
            .ConvertObject("Jackpot!")
            .Returns(stringDatum);
            stringDatumConverter
            .ConvertDatum(Arg.Is <Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str))
            .Returns("Jackpot!");

            IDatumConverter <string> value;

            datumConverterFactory
            .TryGet <string>(queryConverter, out value)
            .Returns(args => {
                args[1] = stringDatumConverter;
                return(true);
            });
        }
        public void TestFixtureSetUp()
        {
            datumConverterFactory = Substitute.For <IDatumConverterFactory>();

            var intDatumConverter = Substitute.For <IDatumConverter>();

            intDatumConverter.ConvertDatum(Arg.Any <Datum>()).Returns(args => (int)((Datum)args[0]).r_num);
            intDatumConverter.ConvertObject(Arg.Any <object>()).Returns(args => new Datum()
            {
                type  = Datum.DatumType.R_NUM,
                r_num = (int)args [0]
            });

            IDatumConverter value;

            datumConverterFactory
            .TryGet(typeof(int), datumConverterFactory, out value)
            .Returns(args =>
            {
                args[2] = intDatumConverter;
                return(true);
            });

            datumConverterFactory.GetBestNativeTypeForDatum(Arg.Any <Datum>()).Returns(typeof(int));
        }
        private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term)
        {
            term = null;

            if (memberExpression.Expression == null)
            {
                // static member access; can't do that server-side, wouldn't want to either.
                return(false);
            }

            if (memberExpression.Expression.NodeType == ExpressionType.Constant)
            {
                // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object
                return(false);
            }

            IDatumConverter datumConverter;

            if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter))
            {
                // No datum converter for this type.
                return(false);
            }

            var fieldConverter = datumConverter as IObjectDatumConverter;

            if (fieldConverter == null)
            {
                // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name
                return(false);
            }

            var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member);

            if (string.IsNullOrEmpty(datumFieldName))
            {
                // At this point we're not returning false because we're expecting this should work; throwing an error instead.
                throw new NotSupportedException(String.Format("Member {0} on type {1} could not be mapped to a datum field", memberExpression.Member.Name, memberExpression.Type));
            }

            var getAttrTerm = new Term()
            {
                type = Term.TermType.GET_FIELD
            };

            getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression));
            getAttrTerm.args.Add(new Term()
            {
                type  = Term.TermType.DATUM,
                datum = new Datum()
                {
                    type  = Datum.DatumType.R_STR,
                    r_str = datumFieldName
                }
            });

            term = getAttrTerm;
            return(true);
        }
Exemple #8
0
        public void TestFixtureSetUp()
        {
            var stringDatum = new Datum()
            {
                type  = Datum.DatumType.R_STR,
                r_str = "Jackpot!",
            };
            var stringDatumConverter = Substitute.For <IDatumConverter <string> >();

            stringDatumConverter
            .ConvertObject("Jackpot!")
            .Returns(stringDatum);
            stringDatumConverter
            .ConvertDatum(Arg.Is <Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str))
            .Returns("Jackpot!");
            ((IDatumConverter)stringDatumConverter)
            .ConvertObject("Jackpot!")
            .Returns(stringDatum);
            ((IDatumConverter)stringDatumConverter)
            .ConvertDatum(Arg.Is <Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str))
            .Returns("Jackpot!");

            rootDatumConverterFactory = Substitute.For <IDatumConverterFactory>();
            IDatumConverter <string> _dcs;

            rootDatumConverterFactory
            .TryGet <string>(rootDatumConverterFactory, out _dcs)
            .Returns(args => {
                Console.WriteLine("TryGet<string>");
                args[1] = stringDatumConverter;
                return(true);
            });
            IDatumConverter _dc;

            rootDatumConverterFactory
            .TryGet(typeof(String), rootDatumConverterFactory, out _dc)
            .Returns(args => {
                args[2] = stringDatumConverter;
                return(true);
            });
        }
        public void TestFixtureSetUp()
        {
            var stringDatum = new Datum() {
                type = Datum.DatumType.R_STR,
                r_str = "Jackpot!",
            };
            var stringDatumConverter = Substitute.For<IDatumConverter<string>>();
            stringDatumConverter
                .ConvertObject("Jackpot!")
                .Returns(stringDatum);
            stringDatumConverter
                .ConvertDatum(Arg.Is<Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str))
                .Returns("Jackpot!");
            ((IDatumConverter)stringDatumConverter)
                .ConvertObject("Jackpot!")
                .Returns(stringDatum);
            ((IDatumConverter)stringDatumConverter)
                .ConvertDatum(Arg.Is<Datum>(d => d.type == stringDatum.type && d.r_str == stringDatum.r_str))
                .Returns("Jackpot!");

            rootDatumConverterFactory = Substitute.For<IDatumConverterFactory>();
            IDatumConverter<string> _dcs;
            rootDatumConverterFactory
                .TryGet<string>(rootDatumConverterFactory, out _dcs)
                .Returns(args => {
                        Console.WriteLine("TryGet<string>");
                        args[1] = stringDatumConverter;
                        return true;
                    });
            IDatumConverter _dc;
            rootDatumConverterFactory
                .TryGet(typeof(String), rootDatumConverterFactory, out _dc)
                .Returns(args => {
                        args[2] = stringDatumConverter;
                        return true;
                    });
        }
Exemple #10
0
        public static IDatumConverter Get(this IDatumConverterFactory datumConverterFactory, Type datumType, IDatumConverterFactory rootDatumConverterFactory)
        {
            if (datumConverterFactory == null)
            {
                throw new ArgumentNullException("datumConverterFactory");
            }
            if (rootDatumConverterFactory == null)
            {
                throw new ArgumentNullException("rootDatumConverterFactory");
            }
            IDatumConverter retval;

            if (datumConverterFactory.TryGet(datumType, rootDatumConverterFactory, out retval))
            {
                return(retval);
            }
            else
            {
                throw new NotSupportedException(String.Format("Datum converter is not available for type {0}", datumType));
            }
        }
        private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term)
        {
            term = null;

            if (memberExpression.Expression == null)
                // static member access; can't do that server-side, wouldn't want to either.
                return false;

            if (memberExpression.Expression.NodeType == ExpressionType.Constant)
                // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object
                return false;

            IDatumConverter datumConverter;
            if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter))
                // No datum converter for this type.
                return false;

            var fieldConverter = datumConverter as IObjectDatumConverter;
            if (fieldConverter == null)
                // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name
                return false;

            var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member);
            if (string.IsNullOrEmpty(datumFieldName))
            {
                // At this point we're not returning false because we're expecting this should work; throwing an error instead.
                // We're expecting this to work, but, returning false will give us a chance to try client-side evaluation instead and
                // maintain compatibility with the pre-PR #209 behaviour. (issue #220).
                return false;
            }

            var getAttrTerm = new Term()
            {
                type = Term.TermType.GET_FIELD
            };
            getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression));
            getAttrTerm.args.Add(new Term()
            {
                type = Term.TermType.DATUM,
                datum = new Datum()
                {
                    type = Datum.DatumType.R_STR,
                    r_str = datumFieldName
                }
            });

            term = getAttrTerm;
            return true;
        }
        private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term)
        {
            term = null;

            if (memberExpression.Expression == null)
                // static member access; can't do that server-side, wouldn't want to either.
                return false;

            if (memberExpression.Expression.NodeType == ExpressionType.Constant)
                // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object
                return false;

            IDatumConverter datumConverter;
            if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter))
                // No datum converter for this type.
                return false;

            var fieldConverter = datumConverter as IObjectDatumConverter;
            if (fieldConverter == null)
                // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name
                return false;

            var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member);
            if (string.IsNullOrEmpty(datumFieldName))
                // At this point we're not returning false because we're expecting this should work; throwing an error instead.
                throw new NotSupportedException(String.Format("Member {0} on type {1} could not be mapped to a datum field", memberExpression.Member.Name, memberExpression.Type));

            var getAttrTerm = new Term()
            {
                type = Term.TermType.GET_FIELD
            };
            getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression));
            getAttrTerm.args.Add(new Term()
            {
                type = Term.TermType.DATUM,
                datum = new Datum()
                {
                    type = Datum.DatumType.R_STR,
                    r_str = datumFieldName
                }
            });

            term = getAttrTerm;
            return true;
        }
Exemple #13
0
        protected Term SimpleMap(IDatumConverterFactory datumConverterFactory, Expression expr)
        {
            switch (expr.NodeType)
            {
            case ExpressionType.Constant:
            {
                var constantExpression = (ConstantExpression)expr;
                var datumConverter     = datumConverterFactory.Get(constantExpression.Type);
                var datum = datumConverter.ConvertObject(constantExpression.Value);
                return(new Term()
                    {
                        type = Term.TermType.DATUM,
                        datum = datum
                    });
            }

            case ExpressionType.Add:
            case ExpressionType.Modulo:
            case ExpressionType.Divide:
            case ExpressionType.Multiply:
            case ExpressionType.Subtract:
            case ExpressionType.Equal:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.AndAlso:
            case ExpressionType.OrElse:
            case ExpressionType.NotEqual:
            case ExpressionType.ArrayIndex:
                return(ConvertBinaryExpressionToTerm((BinaryExpression)expr, datumConverterFactory));

            case ExpressionType.Not:
            case ExpressionType.ArrayLength:
                return(ConvertUnaryExpressionToTerm((UnaryExpression)expr, datumConverterFactory));

            case ExpressionType.New:
            {
                var newExpression = (NewExpression)expr;
                if (AnonymousTypeDatumConverterFactory.Instance.IsTypeSupported(newExpression.Type))
                {
                    var retval = new Term()
                    {
                        type = Term.TermType.MAKE_OBJ,
                    };
                    foreach (var property in newExpression.Type.GetProperties().Select((p, i) => new { Property = p, Index = i }))
                    {
                        var key   = property.Property.Name;
                        var value = RecursiveMap(newExpression.Arguments[property.Index]);
                        retval.optargs.Add(new Term.AssocPair()
                            {
                                key = key, val = value
                            });
                    }
                    return(retval);
                }

                DefaultExpressionConverterFactory.ExpressionMappingDelegate <NewExpression> newExpressionMapping;
                if (expressionConverterFactory.TryGetNewExpressionMapping(newExpression.Constructor, out newExpressionMapping))
                {
                    return(newExpressionMapping(newExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory));
                }

                return(AttemptClientSideConversion(datumConverterFactory, expr));
            }

            case ExpressionType.NewArrayInit:
                var arrayExpression = (NewArrayExpression)expr;
                var array           = new Term {
                    type = Term.TermType.MAKE_ARRAY
                };

                foreach (var expression in arrayExpression.Expressions)
                {
                    array.args.Add(RecursiveMap(expression));
                }

                return(array);

            case ExpressionType.Call:
            {
                var callExpression = (MethodCallExpression)expr;
                var method         = callExpression.Method;

                DefaultExpressionConverterFactory.ExpressionMappingDelegate <MethodCallExpression> methodCallMapping;
                if (expressionConverterFactory.TryGetMethodCallMapping(method, out methodCallMapping))
                {
                    return(methodCallMapping(callExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory));
                }
                else
                {
                    return(AttemptClientSideConversion(datumConverterFactory, expr));
                }
            }

            case ExpressionType.MemberAccess:
            {
                var memberExpression = (MemberExpression)expr;
                var member           = memberExpression.Member;

                DefaultExpressionConverterFactory.ExpressionMappingDelegate <MemberExpression> memberAccessMapping;
                if (expressionConverterFactory.TryGetMemberAccessMapping(member, out memberAccessMapping))
                {
                    return(memberAccessMapping(memberExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory));
                }

                Term serverSideTerm;
                if (ServerSideMemberAccess(datumConverterFactory, memberExpression, out serverSideTerm))
                {
                    return(serverSideTerm);
                }

                return(AttemptClientSideConversion(datumConverterFactory, expr));
            }

            case ExpressionType.Conditional:
            {
                var conditionalExpression = (ConditionalExpression)expr;
                return(new Term()
                    {
                        type = Term.TermType.BRANCH,
                        args =
                        {
                            RecursiveMap(conditionalExpression.Test),
                            RecursiveMap(conditionalExpression.IfTrue),
                            RecursiveMap(conditionalExpression.IfFalse)
                        }
                    });
            }

            case ExpressionType.Convert:
            {
                // The use-case for this right now is automatic boxing that occurs when setting a Dictionary<string,object>'s value
                // to a primitive.  In that particular case, we don't actually need to generate any ReQL for the conversion, so we're
                // just ignoring the Convert and mapping the expression inside.  Might need other behavior here in the future...
                return(RecursiveMap(((UnaryExpression)expr).Operand));
            }

            case ExpressionType.MemberInit:
            {
                var memberInit = (MemberInitExpression)expr;
                var memberType = memberInit.Type;

                IDatumConverter datumConverter;
                if (!datumConverterFactory.TryGet(memberType, out datumConverter))
                {
                    return(AttemptClientSideConversion(datumConverterFactory, expr));
                }

                var fieldConverter = datumConverter as IObjectDatumConverter;
                if (fieldConverter == null)
                {
                    return(AttemptClientSideConversion(datumConverterFactory, expr));
                }

                var makeObjTerm = new Term()
                {
                    type = Term.TermType.MAKE_OBJ,
                };

                foreach (var binding in memberInit.Bindings)
                {
                    switch (binding.BindingType)
                    {
                    case MemberBindingType.Assignment:
                    {
                        var memberAssignment = (MemberAssignment)binding;
                        var pair             = new Term.AssocPair();

                        pair.key = fieldConverter.GetDatumFieldName(memberAssignment.Member);
                        pair.val = RecursiveMap(memberAssignment.Expression);

                        if (pair.key == null)
                        {
                            throw new NotSupportedException("Cannot map member assignments into ReQL without implementing IObjectDatumConverter");
                        }


                        makeObjTerm.optargs.Add(pair);
                        break;
                    }

                    case MemberBindingType.ListBinding:
                    case MemberBindingType.MemberBinding:
                        throw new NotSupportedException("Binding type not currently supported");
                    }
                }

                return(makeObjTerm);
            }

            default:
            {
                return(AttemptClientSideConversion(datumConverterFactory, expr));
            }
            }
        }
        public void TestFixtureSetUp()
        {
            datumConverterFactory = Substitute.For<IDatumConverterFactory>();

            var intDatumConverter = Substitute.For<IDatumConverter>();
            intDatumConverter.ConvertDatum(Arg.Any<Datum>()).Returns(args => (int)((Datum)args[0]).r_num);
            intDatumConverter.ConvertObject(Arg.Any<object>()).Returns(args => new Datum()
            {
                type = Datum.DatumType.R_NUM,
                r_num = (int)args [0]
            });

            IDatumConverter value;
            datumConverterFactory
                .TryGet(typeof(int), datumConverterFactory, out value)
                .Returns(args =>
                {
                    args[2] = intDatumConverter;
                    return true;
                });

            datumConverterFactory.GetBestNativeTypeForDatum(Arg.Any<Datum>()).Returns(typeof(int));
        }
Exemple #15
0
 public static bool TryGet <T>(this IDatumConverterFactory datumConverterFactory, out IDatumConverter <T> datumConverter)
 {
     return(datumConverterFactory.TryGet <T>(datumConverterFactory, out datumConverter));
 }
Exemple #16
0
 public static bool TryGet(this IDatumConverterFactory datumConverterFactory, Type datumType, out IDatumConverter datumConverter)
 {
     return(datumConverterFactory.TryGet(datumType, datumConverterFactory, out datumConverter));
 }
        protected Term SimpleMap(IDatumConverterFactory datumConverterFactory, Expression expr)
        {
            switch (expr.NodeType)
            {
                case ExpressionType.Constant:
                {
                    var constantExpression = (ConstantExpression)expr;
                    var datumConverter = datumConverterFactory.Get(constantExpression.Type);
                    var datum = datumConverter.ConvertObject(constantExpression.Value);
                    return new Term() {
                        type = Term.TermType.DATUM,
                        datum = datum
                    };
                }

                case ExpressionType.Add:
                case ExpressionType.Modulo:
                case ExpressionType.Divide:
                case ExpressionType.Multiply:
                case ExpressionType.Subtract:
                case ExpressionType.Equal:
                case ExpressionType.LessThan:
                case ExpressionType.LessThanOrEqual:
                case ExpressionType.GreaterThan:
                case ExpressionType.GreaterThanOrEqual:
                case ExpressionType.AndAlso:
                case ExpressionType.OrElse:
                case ExpressionType.NotEqual:
                case ExpressionType.ArrayIndex:
                    return ConvertBinaryExpressionToTerm((BinaryExpression)expr, datumConverterFactory);
                case ExpressionType.Not:
                case ExpressionType.ArrayLength:
                    return ConvertUnaryExpressionToTerm((UnaryExpression)expr, datumConverterFactory);

                case ExpressionType.New:
                {
                    var newExpression = (NewExpression)expr;
                    if (AnonymousTypeDatumConverterFactory.Instance.IsTypeSupported(newExpression.Type))
                    {
                        var retval = new Term() {
                            type = Term.TermType.MAKE_OBJ,
                        };
                        foreach (var property in newExpression.Type.GetProperties().Select((p, i) => new { Property = p, Index = i }))
                        {
                            var key = property.Property.Name;
                            var value = RecursiveMap(newExpression.Arguments[property.Index]);
                            retval.optargs.Add(new Term.AssocPair() {
                                key = key, val = value
                            });
                        }
                        return retval;
                    }

                    DefaultExpressionConverterFactory.ExpressionMappingDelegate<NewExpression> newExpressionMapping;
                    if (expressionConverterFactory.TryGetNewExpressionMapping(newExpression.Constructor, out newExpressionMapping))
                        return newExpressionMapping(newExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory);

                    return AttemptClientSideConversion(datumConverterFactory, expr);
                }

                case ExpressionType.NewArrayInit:
                    var arrayExpression = (NewArrayExpression)expr;
                    var array = new Term {type = Term.TermType.MAKE_ARRAY};

                    foreach (var expression in arrayExpression.Expressions)
                    {
                        array.args.Add(RecursiveMap(expression));
                    }

                    return array;

                case ExpressionType.Call:
                {
                    var callExpression = (MethodCallExpression)expr;
                    var method = callExpression.Method;

                    DefaultExpressionConverterFactory.ExpressionMappingDelegate<MethodCallExpression> methodCallMapping;
                    if (expressionConverterFactory.TryGetMethodCallMapping(method, out methodCallMapping))
                        return methodCallMapping(callExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory);
                    else
                        return AttemptClientSideConversion(datumConverterFactory, expr);
                }

                case ExpressionType.MemberAccess:
                {
                    var memberExpression = (MemberExpression)expr;
                    var member = memberExpression.Member;

                    DefaultExpressionConverterFactory.ExpressionMappingDelegate<MemberExpression> memberAccessMapping;
                    if (expressionConverterFactory.TryGetMemberAccessMapping(member, out memberAccessMapping))
                        return memberAccessMapping(memberExpression, RecursiveMap, datumConverterFactory, expressionConverterFactory);

                    Term serverSideTerm;
                    if (ServerSideMemberAccess(datumConverterFactory, memberExpression, out serverSideTerm))
                        return serverSideTerm;

                    return AttemptClientSideConversion(datumConverterFactory, expr);
                }

                case ExpressionType.Conditional:
                {
                    var conditionalExpression = (ConditionalExpression)expr;
                    return new Term()
                    {
                        type = Term.TermType.BRANCH,
                        args = {
                            RecursiveMap(conditionalExpression.Test),
                            RecursiveMap(conditionalExpression.IfTrue),
                            RecursiveMap(conditionalExpression.IfFalse)
                        }
                    };
                }

                case ExpressionType.Convert:
                {
                    // The use-case for this right now is automatic boxing that occurs when setting a Dictionary<string,object>'s value
                    // to a primitive.  In that particular case, we don't actually need to generate any ReQL for the conversion, so we're
                    // just ignoring the Convert and mapping the expression inside.  Might need other behavior here in the future...
                    return RecursiveMap(((UnaryExpression)expr).Operand);
                }

                case ExpressionType.MemberInit:
                {
                    var memberInit = (MemberInitExpression)expr;
                    var memberType = memberInit.Type;

                    IDatumConverter datumConverter;
                    if (!datumConverterFactory.TryGet(memberType, out datumConverter))
                        return AttemptClientSideConversion(datumConverterFactory, expr);

                    var fieldConverter = datumConverter as IObjectDatumConverter;
                    if (fieldConverter == null)
                        return AttemptClientSideConversion(datumConverterFactory, expr);

                    var makeObjTerm = new Term() {
                        type = Term.TermType.MAKE_OBJ,
                    };

                    foreach (var binding in memberInit.Bindings)
                    {
                        switch (binding.BindingType)
                        {
                            case MemberBindingType.Assignment:
                            {
                                var memberAssignment = (MemberAssignment)binding;
                                var pair = new Term.AssocPair();

                                pair.key = fieldConverter.GetDatumFieldName(memberAssignment.Member);
                                pair.val = RecursiveMap(memberAssignment.Expression);

                                if (pair.key == null)
                                    throw new NotSupportedException("Cannot map member assignments into ReQL without implementing IObjectDatumConverter");

                                makeObjTerm.optargs.Add(pair);
                                break;
                            }
                            case MemberBindingType.ListBinding:
                            case MemberBindingType.MemberBinding:
                                throw new NotSupportedException("Binding type not currently supported");
                        }
                    }

                    return makeObjTerm;
                }

                default:
                {
                    return AttemptClientSideConversion(datumConverterFactory, expr);
                }
            }
        }
 public bool TryGet(Type datumType, IDatumConverterFactory rootDatumConverterFactory, out IDatumConverter datumConverter)
 {
     return(delegatedDatumConverterFactory.TryGet(datumType, rootDatumConverterFactory, out datumConverter));
 }
Exemple #19
0
        private bool ServerSideMemberAccess(IDatumConverterFactory datumConverterFactory, MemberExpression memberExpression, out Term term)
        {
            term = null;

            if (memberExpression.Expression == null)
            {
                // static member access; can't do that server-side, wouldn't want to either.
                return(false);
            }

            if (memberExpression.Expression.NodeType == ExpressionType.Constant)
            {
                // Accessing a constant; client-side conversion will be more efficient since we won't be round-tripping the object
                return(false);
            }

            IDatumConverter datumConverter;

            if (!datumConverterFactory.TryGet(memberExpression.Expression.Type, out datumConverter))
            {
                // No datum converter for this type.
                return(false);
            }

            var fieldConverter = datumConverter as IObjectDatumConverter;

            if (fieldConverter == null)
            {
                // doesn't implement IObjectDatumConverter, so we don't know how to map the MemberInfo to the field name
                return(false);
            }

            var datumFieldName = fieldConverter.GetDatumFieldName(memberExpression.Member);

            if (string.IsNullOrEmpty(datumFieldName))
            {
                // At this point we're not returning false because we're expecting this should work; throwing an error instead.
                // We're expecting this to work, but, returning false will give us a chance to try client-side evaluation instead and
                // maintain compatibility with the pre-PR #209 behaviour. (issue #220).
                return(false);
            }

            var getAttrTerm = new Term()
            {
                type = Term.TermType.GET_FIELD
            };

            getAttrTerm.args.Add(RecursiveMap(memberExpression.Expression));
            getAttrTerm.args.Add(new Term()
            {
                type  = Term.TermType.DATUM,
                datum = new Datum()
                {
                    type  = Datum.DatumType.R_STR,
                    r_str = datumFieldName
                }
            });

            term = getAttrTerm;
            return(true);
        }