csharp/0x1000000/SqExpress/SqExpress/ExprExtension.cs

ExprExtension.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Xml;
using SqExpress.DataAccess;
using SqExpress.QueryBuilders;
using SqExpress.QueryBuilders.Update;
using SqExpress.Syntax;
using SqExpress.SyntaxTreeOperations;
using SqExpress.SyntaxTreeOperations.ExportImport;
using SqExpress.SyntaxTreeOperations.ExportImport.Internal;
using SqExpress.SyntaxTreeOperations.Internal;

namespace SqExpress
{
    public static clast ExprExtension
    {
        //Sync handler
        public static Task Query(this IExprQuery query, ISqDatabase database, TAgg seed, Func aggregator) 
            => database.Query(query, seed, aggregator);

        public static Task Query(this IExprQueryFinal query, ISqDatabase database, TAgg seed, Func aggregator) 
            => database.Query(query.Done(), seed, aggregator);

        public static Task Query(this IExprQuery query, ISqDatabase database, Action handler) 
            => database.Query(query, handler);

        public static Task Query(this IExprQueryFinal query, ISqDatabase database, Action handler) 
            => database.Query(query.Done(), handler);

        //Async handler
        public static Task Query(this IExprQuery query, ISqDatabase database, TAgg seed, Func aggregator) 
            => database.Query(query, seed, aggregator);

        public static Task Query(this IExprQueryFinal query, ISqDatabase database, TAgg seed, Func aggregator) 
            => database.Query(query.Done(), seed, aggregator);

        public static Task Query(this IExprQuery query, ISqDatabase database, Func handler) 
            => database.Query(query, handler);

        public static Task Query(this IExprQueryFinal query, ISqDatabase database, Func handler) 
            => database.Query(query.Done(), handler);

        public static Task QueryList(this IExprQuery query, ISqDatabase database, Func factory) 
            => database.QueryList(query, factory);

        public static Task QueryList(this IExprQueryFinal query, ISqDatabase database, Func factory) 
            => database.QueryList(query.Done(), factory);

        public static Task QueryDictionary(
            this IExprQuery query, 
            ISqDatabase database, 
            Func keyFactory,
            Func valueFactory, 
            SqDatabaseExtensions.KeyDuplicationHandler? keyDuplicationHandler = null,
            Func? predicate = null)
        where TKey : notnull
            => database.QueryDictionary(query, keyFactory, valueFactory, keyDuplicationHandler, predicate);

        public static Task QueryDictionary(
            this IExprQueryFinal query, 
            ISqDatabase database, 
            Func keyFactory,
            Func valueFactory, 
            SqDatabaseExtensions.KeyDuplicationHandler? keyDuplicationHandler = null,
            Func? predicate = null)
        where TKey : notnull
            => database.QueryDictionary(query.Done(), keyFactory, valueFactory, keyDuplicationHandler, predicate);

        public static Task QueryScalar(this IExprQuery query, ISqDatabase database)
            => database.QueryScalar(query);

        public static Task QueryScalar(this IExprQueryFinal query, ISqDatabase database)
            => database.QueryScalar(query.Done());

        public static Task Exec(this IExprExec query, ISqDatabase database)
            => database.Exec(query);

        public static Task Exec(this IExprExecFinal query, ISqDatabase database)
            => database.Exec(query.Done());

        public static Task Exec(this IUpdateDataBuilderFinal builder, ISqDatabase database)
            => database.Exec(builder.Done());

        public static SyntaxTreeActions SyntaxTree(this IExpr expr)
        {
            return new SyntaxTreeActions(expr);
        }

        public readonly struct SyntaxTreeActions
        {
            private readonly IExpr _expr;

            internal SyntaxTreeActions(IExpr expr)
            {
                this._expr = expr;
            }

            public void WalkThrough(IWalkerVisitor walkerVisitor, TCtx context)
            {
                this._expr.Accept(new ExprWalker(walkerVisitor), context);
            }

            public void WalkThrough(Func walker, TCtx context)
            {
                this._expr.Accept(new ExprWalker(new DefaultWalkerVisitor(walker)), context);
            }

            public IEnumerable Descendants()
            {
                return ExprWalkerPull.GetEnumerable(this._expr, false);
            }

            public IEnumerable DescendantsAndSelf()
            {
                return ExprWalkerPull.GetEnumerable(this._expr, true);
            }

            public TExpr? FirstOrDefault(Predicate? filter = null) where TExpr : clast, IExpr
            {
                TExpr? result = null;
                this._expr.Accept(new ExprWalker(new DefaultWalkerVisitor((e, c) =>
                {
                    if (e is TExpr te && (filter == null || filter.Invoke(te)))
                    {
                        result = te;
                        return VisitorResult.Stop(c);
                    }
                    return VisitorResult.Continue(c);
                })), null);
                return result;
            }

            public IExpr? Modify(Func modifier)
            {
                return this._expr.Accept(ExprModifier.Instance, modifier);
            }

            public IExpr? Modify(Func modifier) where TExpr: IExpr
            {
                return this._expr.Accept(ExprModifier.Instance,
                    e =>
                    {
                        if (e is TExpr te)
                        {
                            return modifier(te);
                        }
                        return e;
                    });
            }

            public IReadOnlyList ExportToPlainList(PlainItemFactory plainItemFactory) where T : IPlainItem
            {
                var walkerVisitor = new ExprPlainWriter(plainItemFactory);
                WalkThrough(walkerVisitor, 0);
                return walkerVisitor.Result;
            }

            public void ExportToXml(XmlWriter xmlWriter)
            {
                var walkerVisitor = new ExprXmlWriter();
                WalkThrough(walkerVisitor, xmlWriter);
            }
#if NETCOREAPP
            public void ExportToJson(System.Text.Json.Utf8JsonWriter jsonWriter)
            {
                var walkerVisitor = new ExprJsonWriter();
                WalkThrough(walkerVisitor, jsonWriter);
            }
#endif
        }
    }
}