예제 #1
0
        internal static IAggregate <TInput, TState, TResult> TransformOutput <TInput, TState, TAggregateResult, TResult>(
            this IAggregate <TInput, TState, TAggregateResult> aggregate,
            Expression <Func <TAggregateResult, TResult> > transform)
        {
            Contract.Requires(aggregate != null);
            Contract.Requires(transform != null);

            return(GeneratedAggregate.Create(
                       initialState: aggregate.InitialState(),
                       accumulate: aggregate.Accumulate(),
                       deaccumulate: aggregate.Deaccumulate(),
                       difference: aggregate.Difference(),
                       computeResult: aggregate.ComputeResult().TransformOutput(transform)));
        }
예제 #2
0
        public static IAggregate <TInput?, TState, TResult> MakeInputNullableAndSkipNulls <TInput, TState, TResult>(
            this IAggregate <TInput, TState, TResult> aggregate) where TInput : struct
        {
            Contract.Requires(aggregate != null);

            Expression <Func <TState, long, TInput?, TState> > newAccumulate = (oldState, timestamp, input) =>
                                                                               input.HasValue ? CallInliner.Call(aggregate.Accumulate(), oldState, timestamp, input.Value) : oldState;

            Expression <Func <TState, long, TInput?, TState> > newDeaccumulate = (oldState, timestamp, input) =>
                                                                                 input.HasValue ? CallInliner.Call(aggregate.Deaccumulate(), oldState, timestamp, input.Value) : oldState;

            return(GeneratedAggregate.Create(
                       initialState: aggregate.InitialState(),
                       accumulate: newAccumulate.InlineCalls(),
                       deaccumulate: newDeaccumulate.InlineCalls(),
                       difference: aggregate.Difference(),
                       computeResult: aggregate.ComputeResult()));
        }
예제 #3
0
        public static IAggregate <TInput, NullOutputWrapper <TState>, TResult> OutputDefaultWhenEmpty <TInput, TState, TResult>(
            this IAggregate <TInput, TState, TResult> aggregate)
        {
            Contract.Requires(aggregate != null);

            Expression <Func <NullOutputWrapper <TState> > > newInitialState =
                () => new NullOutputWrapper <TState>
            {
                Count = 0,
                State = CallInliner.Call(aggregate.InitialState())
            };

            Expression <Func <NullOutputWrapper <TState>, long, TInput, NullOutputWrapper <TState> > > newAccumulate =
                (oldState, timestamp, input) => new NullOutputWrapper <TState>
            {
                Count = oldState.Count + 1,
                State = CallInliner.Call(aggregate.Accumulate(), oldState.State, timestamp, input)
            };

            Expression <Func <NullOutputWrapper <TState>, long, TInput, NullOutputWrapper <TState> > > newDeaccumulate =
                (oldState, timestamp, input) => new NullOutputWrapper <TState>
            {
                Count = oldState.Count - 1,
                State = CallInliner.Call(aggregate.Deaccumulate(), oldState.State, timestamp, input)
            };

            Expression <Func <NullOutputWrapper <TState>, NullOutputWrapper <TState>, NullOutputWrapper <TState> > > newDifference =
                (leftState, rightState) => new NullOutputWrapper <TState>
            {
                Count = leftState.Count - rightState.Count,
                State = CallInliner.Call(aggregate.Difference(), leftState.State, rightState.State)
            };

            Expression <Func <NullOutputWrapper <TState>, TResult> > newComputeResult =
                state => state.Count == 0 ? default : CallInliner.Call(aggregate.ComputeResult(), state.State);

                return(GeneratedAggregate.Create(
                           initialState: newInitialState.InlineCalls(),
                           accumulate: newAccumulate.InlineCalls(),
                           deaccumulate: newDeaccumulate.InlineCalls(),
                           difference: newDifference.InlineCalls(),
                           computeResult: newComputeResult.InlineCalls()));
        }
예제 #4
0
        public static IAggregate <TInput, TState, TResult> SkipNulls <TInput, TState, TResult>(
            this IAggregate <TInput, TState, TResult> aggregate)
        {
            Contract.Requires(aggregate != null);

            var inputType = typeof(TInput).GetTypeInfo();

            return(inputType.IsClass
                ? GeneratedAggregate.Create(
                       initialState: aggregate.InitialState(),
                       accumulate: AddSkipNullClassLogic(aggregate.Accumulate()),
                       deaccumulate: AddSkipNullClassLogic(aggregate.Deaccumulate()),
                       difference: aggregate.Difference(),
                       computeResult: aggregate.ComputeResult())
                : inputType.IsGenericType && inputType.GetGenericTypeDefinition() == typeof(Nullable <>)
                ? GeneratedAggregate.Create(
                       initialState: aggregate.InitialState(),
                       accumulate: AddSkipNullValueLogic(aggregate.Accumulate()),
                       deaccumulate: AddSkipNullValueLogic(aggregate.Deaccumulate()),
                       difference: aggregate.Difference(),
                       computeResult: aggregate.ComputeResult())
                : aggregate);
        }
예제 #5
0
        public static IAggregate <TInput, TState, TResult> ApplyFilter <TInput, TState, TResult>(
            this IAggregate <TInput, TState, TResult> aggregate,
            Expression <Func <TInput, bool> > filter)
        {
            Contract.Requires(aggregate != null);
            if (filter == null || filter.Body.ExpressionEquals(Expression.Constant(true)))
            {
                return(aggregate);
            }

            Expression <Func <TState, long, TInput, TState> > newAccumulate = (oldState, timestamp, input) =>
                                                                              CallInliner.Call(filter, input) ? CallInliner.Call(aggregate.Accumulate(), oldState, timestamp, input) : oldState;

            Expression <Func <TState, long, TInput, TState> > newDeaccumulate = (oldState, timestamp, input) =>
                                                                                CallInliner.Call(filter, input) ? CallInliner.Call(aggregate.Deaccumulate(), oldState, timestamp, input) : oldState;

            return(GeneratedAggregate.Create(
                       initialState: aggregate.InitialState(),
                       accumulate: newAccumulate.InlineCalls(),
                       deaccumulate: newDeaccumulate.InlineCalls(),
                       difference: aggregate.Difference(),
                       computeResult: aggregate.ComputeResult()));
        }