zoukankan      html  css  js  c++  java
  • 扩展MongoDB C# Driver的QueryBuilder

    扩展MongoDB C# Driver的QueryBuilder


    因为不想直接hardcode "ClassA.MemberA.MemberB" 这种字符串 。写了下面几个类,用于下面经常使用的场景:
    1. 表达式转换成字符串函数: ExpToStr()
    2. Collection函数:当有集合成员时,能够使用此类,将返回QueryCollection对象,这个类的代码之后附上
    3. CollectionAs函数:当使用了继承。希望将基类转换为子类并返回子类的QueryCollection


    使用演示样例:


    //获得表达式的字符串形式
    1. QueryEx<ClassA>.ExpToStr ((ClassA m)=> m.MemberA.MemberB.MemberC)
    
    
    //集合.成员.字段
    //PoppedSegments为集合,AssignedNetwork.Name为成员
    //将返回PoppedSegments.AssignedNetwork.Name
    2. QueryEx<MDDelivery>.Collection(x => x.PoppedSegments).Matches(p => p.AssignedNetwork.Name, bsonRegex),
    
    
    //子类集合.成员.字段
    //STPaymentTransaction为基类,STPaymentCompanyCredit为子类,Company字段在子类中
    //将返回Payments.Company.Name
    3. QueryEx<MDDelivery>.CollectionAs<STPaymentTransaction, STPaymentCompanyCredit>(x=>x.Payments).Matches(p=>p.Company.Name, bsonRegex)
    
    
    //集合.集合.成员.字段
    //Parcels为集合,STCustomPropertyRuntime为基类,STNumericPropertyRuntime为子类,CustomProps为STNumericPropertyRuntime中成员,Value为CustomProp中成员
    //将返回Parcels.CustomProps.Value
    4. QueryEx<MDDelivery>.Collection(x=>x.Parcels).CollectionMemberAs<STCustomPropertyRuntime, STNumericPropertyRuntime>(p=>p.CustomProps).Matches(p=>p.Value, bsonRegex),




    实现代码:


    public class QueryEx<TDocument>
        {
            public static QueryCollection<TDocument, TCollection> Collection<TCollection>(
                Expression<Func<TDocument, IEnumerable<TCollection>>> collectionExpression)
            {
                return new QueryCollection<TDocument, TCollection>(collectionExpression);
            }
    
    
            //for those cases using inheritance
            //e.g STPaymentTransaction
            //Payments will return STPaymentTransaction 
            //need to cast to sub classes(STPaymentCompanyCredit) so that be able to filter by child members (e.g. Company)
            public static QueryCollection<TDocument, TSub> CollectionAs<TCollection, TSub>(
                Expression<Func<TDocument, IEnumerable<TCollection>>> collectionExpression)
                where TSub : TCollection
            {
                var argParam = Expression.Parameter(typeof (TDocument), "x");
                var memberStr = ExpToStr(collectionExpression);
                MemberExpression nameProperty = Expression.Property(argParam, memberStr);
    
    
                var subExp = Expression.Convert(nameProperty, typeof(IEnumerable<TSub>));
    
    
                var exp = Expression.Lambda<Func<TDocument, IEnumerable<TSub>>>(
                    subExp,
                    argParam);
    
    
                return new QueryCollection<TDocument, TSub>(exp);
            }
    
    
            /// <summary>
            /// return string value for a expression:
            /// for s.Name.Val1.Val2 will return Name.Val1.Val2
            /// </summary>
            /// <typeparam name="MDClass"></typeparam>
            /// <typeparam name="Member"></typeparam>
            /// <param name="exp"></param>
            /// <returns></returns>
            public static string ExpToStr<TDocument, Member>(Expression<Func<TDocument, Member>> exp)
            {
                return new QueryExpressionHelper().MemberExpression(exp);
            }
        }
    
    
    
    
    
    
    
    
    public class QueryCollection<TDocument, TCollection>
        {
            private readonly QueryExpressionHelper _queryExpression;
            private string _collectionName;
    
    
            public string Context
            {
                get { return _collectionName; }
            }
    
    
            public QueryCollection(Expression<Func<TDocument, IEnumerable<TCollection>>> collectionExpression)
            {
                _queryExpression = new QueryExpressionHelper();
                _collectionName = _queryExpression.MemberExpression(collectionExpression);
            }
    
    
            public QueryMember<TCollection, TMember> Member<TMember>(Expression<Func<TCollection, TMember>> exp)
            {
                var expStr = QueryEx<TCollection>.ExpToStr(exp);
                var context = string.Format("{0}.{1}", _collectionName, expStr);
                var obj = new QueryMember<TCollection, TMember>(context);
    
    
                return obj;
            }
    
    
            public QueryCollection<TCollection, TMember> CollectionMember<TMember>(
                Expression<Func<TCollection, IEnumerable<TMember>>> exp)
            {
                var expStr = QueryEx<TCollection>.ExpToStr(exp);
                var obj = new QueryCollection<TCollection, TMember>(exp)
                {
                    _collectionName = string.Format("{0}.{1}", _collectionName, expStr)
                };
    
    
                return obj;
            }
    
    
            /// <summary>
            /// this method only support 1 layer nested(not for Query Collection.Collection , but for Collection.Member)
            /// if member is collection and need convert to sub class 
            /// </summary>
            /// <typeparam name="TMember">Base Type</typeparam>
            /// <typeparam name="TMemberSub">Child Class Type</typeparam>
            /// <param name="collectionExpression"></param>
            /// <returns></returns>
            public QueryCollection<TCollection, TMemberSub> CollectionMemberAs<TMember, TMemberSub>(
                Expression<Func<TCollection, IEnumerable<TMember>>> collectionExpression)
                where TMemberSub : TMember
            {
                var obj = QueryEx<TCollection>.CollectionAs<TMember, TMemberSub>(collectionExpression);
                obj._collectionName = string.Format("{0}.{1}", _collectionName, obj._collectionName);
    
    
                return obj;
            }
    
    
            public IMongoQuery LT<TMember>(Expression<Func<TCollection, TMember>> memberExpression, TMember value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.LT(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
            }
    
    
            public IMongoQuery LT<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, TValue value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.LT(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
            }
    
    
            public IMongoQuery EQ<TMember>(Expression<Func<TCollection, TMember>> memberExpression, TMember value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.EQ(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
            }
    
    
            public IMongoQuery EQ<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, TValue value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.EQ(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
            }
    
    
            public IMongoQuery NE<TMember>(Expression<Func<TCollection, TMember>> memberExpression, TMember value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.NE(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
            }
    
    
            public IMongoQuery NE<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, TValue value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.NE(string.Format("{0}.{1}", _collectionName, memberName), BsonValue.Create(value));
            }
    
    
            public IMongoQuery In<TMember>(Expression<Func<TCollection, TMember>> memberExpression, params TMember[] values)
            {
                return In<TMember>(memberExpression, new List<TMember>(values));
            }
    
    
            public IMongoQuery In<TMember>(Expression<Func<TCollection, TMember>> memberExpression,
                IEnumerable<TMember> values)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
                return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
            }
    
    
            public IMongoQuery In<TCastC, TMember>(Expression<Func<TCastC, TMember>> memberExpression,
                IEnumerable<TMember> values) where TCastC : TCollection
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
                return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
            }
    
    
            public IMongoQuery In<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, IEnumerable<TValue> values)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
                return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
            }
    
    
            public IMongoQuery In<TCastC, TValue>(Expression<Func<TCastC, IEnumerable<TValue>>> memberExpression, IEnumerable<TValue> values) where TCastC : TCollection
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
                return Query.In(string.Format("{0}.{1}", _collectionName, memberName), values.Select(x => BsonValue.Create(x)));
            }
    
    
    
    
            public IMongoQuery Matches<TMember>(Expression<Func<TCollection, TMember>> memberExpression, BsonRegularExpression value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.Matches(string.Format("{0}.{1}", _collectionName, memberName), value);
            }
    
    
            public IMongoQuery Matches<TValue>(Expression<Func<TCollection, IEnumerable<TValue>>> memberExpression, BsonRegularExpression value)
            {
                var memberName = _queryExpression.MemberExpression(memberExpression);
    
    
                return Query.Matches(string.Format("{0}.{1}", _collectionName, memberName), value);
            }
        }
    
    
    
    
    
    
    
    
    public class QueryMember<TDocument, TCollection>
        {
            private readonly QueryExpressionHelper _queryExpression;
            private string _collectionName;
    
    
            public string Context
            {
                get { return _collectionName; }
            }
    
    
            public QueryMember(Expression<Func<TDocument, TCollection>> exp)
            {
                _queryExpression = new QueryExpressionHelper();
                _collectionName = _queryExpression.MemberExpression(exp);
            }
    
    
            public QueryMember(string context)
            {
                _collectionName = context;
            }
    
    
        }
    
    
    
    
    public class QueryExpressionHelper
        {
            public string Context;
    
    
            public string MemberExpression<TMember>(Expression<TMember> expression)
            {
                MemberExpression me;
                switch (expression.Body.NodeType)
                {
                    case ExpressionType.MemberAccess:
                        me = expression.Body as MemberExpression;
                        break;
                    case ExpressionType.Convert:
                        dynamic convertedBody = expression.Body;
                        me = convertedBody.Operand as MemberExpression;
                        break;
    
    
                    default:
                        throw new NotSupportedException(string.Format("Member with node type {0} is not supported. expression {1}", expression.Body.NodeType, expression));
                }
                var stack = new Stack<string>();
    
    
                while (me != null)
                {
                    stack.Push(me.Member.Name);
                    me = me.Expression as MemberExpression;
                }
    
    
                var expStr = string.Join(".", stack.ToArray());
                return expStr;
    
    
               
            }
        }
    
    
    
    
    public static class QueryMoney
        {
            public static IMongoQuery Value(string name, double val)
            {
                var accuracy = 0.005;
    
    
                return Query.And(
                    Query.LT(name, new BsonDouble(val + accuracy)),
                    Query.GT(name, new BsonDouble(val - accuracy)));
            }
        }


  • 相关阅读:
    Intellij IDEA使用restclient测试
    jmeter测试
    Java中String为什么是不可变的
    为什么String类是不可变的?
    反射中getMethods 与 getDeclaredMethods 的区别
    MD5加密
    将long型转换为多少MB的方法
    ContentProvider往通讯录添加联系人和获取联系人
    安卓软件版本更新
    Servlet生命周期与工作原理
  • 原文地址:https://www.cnblogs.com/llguanli/p/6840147.html
Copyright © 2011-2022 走看看