예제 #1
0
        protected internal virtual ExtensionToken CreateToken(QueryToken parent)
        {
            var info = metas.GetOrAdd(parent, qt =>
            {
                Expression e = MetadataVisitor.JustVisit(Lambda, MetaExpression.FromToken(qt, SourceType));

                MetaExpression me;

                if (this.IsProjection)
                {
                    var mpe = e as MetaProjectorExpression;

                    if (mpe == null)
                    {
                        mpe = MetadataVisitor.AsProjection(e);
                    }

                    me = mpe == null ? null : mpe.Projector as MetaExpression;
                }
                else
                {
                    me = e as MetaExpression;
                }

                CleanMeta cm = me == null ? null : me.Meta as CleanMeta;

                var result = new ExtensionRouteInfo();

                if (cm != null && cm.PropertyRoutes.Any())
                {
                    var cleanType = me.Type.CleanType();

                    result.PropertyRoute   = cm.PropertyRoutes.Only();
                    result.Implementations = me.Meta.Implementations;
                    result.Format          = ColumnDescriptionFactory.GetFormat(cm.PropertyRoutes);
                    result.Unit            = ColumnDescriptionFactory.GetUnit(cm.PropertyRoutes);
                }

                result.IsAllowed = () => (me == null || me.Meta == null) ? null : me.Meta.IsAllowed();

                if (ForcePropertyRoute != null)
                {
                    result.PropertyRoute = ForcePropertyRoute;
                }

                if (ForceImplementations != null)
                {
                    result.Implementations = ForceImplementations;
                }

                if (ForceFormat != null)
                {
                    result.Format = ForceFormat;
                }

                if (ForceUnit != null)
                {
                    result.Unit = ForceUnit;
                }

                if (ForceIsAllowed != null)
                {
                    result.IsAllowed = ForceIsAllowed;
                }

                return(result);
            });

            return(new ExtensionToken(parent, Key, Type, IsProjection, info.Unit, info.Format, info.Implementations, info.IsAllowed(), info.PropertyRoute)
            {
                DisplayName = NiceName()
            });
        }
예제 #2
0
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable) ||
                m.Method.DeclaringType == typeof(Enumerable) ||
                m.Method.DeclaringType == typeof(EnumerableUniqueExtensions))
            {
                switch (m.Method.Name)
                {
                case "Where":
                    return(this.BindWhere(m.Type, m.GetArgument("source"), m.GetArgument("predicate").StripQuotes()));

                case "Select":
                    return(this.BindSelect(m.Type, m.GetArgument("source"), m.GetArgument("selector").StripQuotes()));

                case "SelectMany":
                    if (m.Arguments.Count == 2)
                    {
                        return(this.BindSelectMany(m.Type, m.GetArgument("source"), m.GetArgument("selector").StripQuotes(), null));
                    }
                    else
                    {
                        return(this.BindSelectMany(m.Type, m.GetArgument("source"), m.GetArgument("collectionSelector").StripQuotes(), m.TryGetArgument("resultSelector").StripQuotes()));
                    }

                case "Join":
                    return(this.BindJoin(
                               m.Type, m.GetArgument("outer"), m.GetArgument("inner"),
                               m.GetArgument("outerKeySelector").StripQuotes(),
                               m.GetArgument("innerKeySelector").StripQuotes(),
                               m.GetArgument("resultSelector").StripQuotes()));

                case "OrderBy":
                    return(this.BindOrderBy(m.Type, m.GetArgument("source"), m.GetArgument("keySelector").StripQuotes(), OrderType.Ascending));

                case "OrderByDescending":
                    return(this.BindOrderBy(m.Type, m.GetArgument("source"), m.GetArgument("keySelector").StripQuotes(), OrderType.Descending));

                case "ThenBy":
                    return(this.BindThenBy(m.GetArgument("source"), m.GetArgument("keySelector").StripQuotes(), OrderType.Ascending));

                case "ThenByDescending":
                    return(this.BindThenBy(m.GetArgument("source"), m.GetArgument("keySelector").StripQuotes(), OrderType.Descending));

                case "GroupBy":
                    return(this.BindGroupBy(m.Type, m.GetArgument("source"),
                                            m.GetArgument("keySelector").StripQuotes(),
                                            m.GetArgument("elementSelector").StripQuotes()));

                case "Count":
                    return(this.BindCount(m.Type, m.GetArgument("source")));

                case "DefaultIfEmpty":
                    return(Visit(m.GetArgument("source")));

                case "Any":
                    return(this.BindAny(m.Type, m.GetArgument("source")));

                case "All":
                    return(this.BindAll(m.Type, m.GetArgument("source"), m.GetArgument("predicate").StripQuotes()));

                case "Contains":
                    return(this.BindContains(m.Type, m.GetArgument("source"), m.TryGetArgument("item") ?? m.GetArgument("value")));

                case "Sum":
                case "Min":
                case "Max":
                case "Average":
                    return(this.BindAggregate(m.Type, m.Method.Name.ToEnum <AggregateSqlFunction>(),
                                              m.GetArgument("source"), m.TryGetArgument("selector").StripQuotes()));

                case "First":
                case "FirstOrDefault":
                case "Single":
                case "SingleOrDefault":
                    return(BindUniqueRow(m.Type, m.Method.Name.ToEnum <UniqueFunction>(),
                                         m.GetArgument("source"), m.TryGetArgument("predicate").StripQuotes()));

                case "FirstEx":
                case "SingleEx":
                case "SingleOrDefaultEx":
                    return(BindUniqueRow(m.Type, m.Method.Name.RemoveEnd(2).ToEnum <UniqueFunction>(),
                                         m.GetArgument("collection"), m.TryGetArgument("predicate").StripQuotes()));

                case "Distinct":
                    return(BindDistinct(m.Type, m.GetArgument("source")));

                case "Take":
                    return(BindTake(m.Type, m.GetArgument("source"), m.GetArgument("count")));

                case "Skip":
                    return(BindSkip(m.Type, m.GetArgument("source"), m.GetArgument("count")));
                }
            }

            if (m.Method.Name == "Mixin" && m.Method.GetParameters().Length == 0)
            {
                var obj = Visit(m.Object);

                if (obj is MetaExpression me && me.Meta is CleanMeta)
                {
                    CleanMeta cm = (CleanMeta)me.Meta;

                    var mixinType = m.Method.GetGenericArguments().Single();

                    return(new MetaExpression(mixinType, new CleanMeta(null, cm.PropertyRoutes.Select(a => a.Add(mixinType)).ToArray())));
                }
            }

            if (m.Method.DeclaringType == typeof(LinqHints) || m.Method.DeclaringType == typeof(LinqHintEntities))
            {
                return(Visit(m.Arguments[0]));
            }

            if (m.Method.DeclaringType == typeof(StringExtensions) && m.Method.Name == nameof(StringExtensions.Etc))
            {
                return(Visit(m.Arguments[0]));
            }

            if (m.Method.DeclaringType == typeof(Lite) && m.Method.Name == "ToLite")
            {
                return(MakeCleanMeta(m.Type, Visit(m.Arguments[0])));
            }

            if (m.Method.DeclaringType == typeof(Math) &&
                (m.Method.Name == "Abs" ||
                 m.Method.Name == "Ceiling" ||
                 m.Method.Name == "Floor" ||
                 m.Method.Name == "Round" ||
                 m.Method.Name == "Truncate"))
            {
                return(MakeCleanMeta(m.Type, Visit(m.Arguments[0])));
            }

            if (m.Method.Name == "ToString" && m.Object != null && typeof(IEntity).IsAssignableFrom(m.Object.Type))
            {
                return(Visit(Expression.Property(m.Object, piToStringProperty)));
            }

            if (m.Object != null)
            {
                var a    = this.Visit(m.Object);
                var list = this.Visit(m.Arguments);
                return(MakeDirtyMeta(m.Type, null, list.PreAnd(a).ToArray()));
            }
            else
            {
                var list = this.Visit(m.Arguments);
                return(MakeDirtyMeta(m.Type, null, list.ToArray()));
            }
        }
예제 #3
0
 public MetaMListExpression(Type type, CleanMeta parent, CleanMeta element)
     : base(MetaExpressionType.MetaMListExpression, type)
 {
     this.Parent  = parent;
     this.Element = element;
 }