コード例 #1
0
        internal static Expression <Comparison <T2> > CreateCompoundComparer <T1, T2>(Expression <Func <T2, T1> > selector, Expression <Comparison <T1> > comparer)
        {
            var newParam1 = Expression.Parameter(selector.Parameters[0].Type, selector.Parameters[0].Name + "_1");
            var newParam2 = Expression.Parameter(selector.Parameters[0].Type, selector.Parameters[0].Name + "_2");
            var copy1     = ParameterInliner.Inline(selector, newParam1);
            var copy2     = ParameterInliner.Inline(selector, newParam2);
            var result    = ParameterInliner.Inline(comparer, copy1, copy2);

            return(Expression.Lambda <Comparison <T2> >(result, newParam1, newParam2));
        }
コード例 #2
0
        private static Expression <Func <T1, TOutput> > TransformOutput <T1, TFuncOutput, TOutput>(
            this Expression <Func <T1, TFuncOutput> > func,
            Expression <Func <TFuncOutput, TOutput> > transform)
        {
            Contract.Requires(func != null);
            Contract.Requires(transform != null);
            var result = ParameterInliner.Inline(transform, func.Body);

            return(Expression.Lambda <Func <T1, TOutput> >(result, func.Parameters));
        }
コード例 #3
0
        private static Expression <Func <T1, T2, TInput, TOutput> > TransformInput3 <T1, T2, T3, TInput, TOutput>(
            this Expression <Func <T1, T2, T3, TOutput> > func,
            Expression <Func <TInput, T3> > transform)
        {
            Contract.Requires(func != null);
            Contract.Requires(transform != null);
            var result         = ParameterInliner.Inline(func, func.Parameters[0], func.Parameters[1], transform.Body);
            var transformParam = transform.Parameters[0];

            return(Expression.Lambda <Func <T1, T2, TInput, TOutput> >(result, new[] { func.Parameters[0], func.Parameters[1], transformParam }));
        }
コード例 #4
0
        private static Tuple <Expression, Expression> MakeEqualityAndHashCodeExpressions(ParameterExpression left, ParameterExpression right, ParameterExpression a, Type pType, string pName)
        {
            var equalityComparerTypeForPropertyType = typeof(EqualityComparerExpression <>).MakeGenericType(pType);
            var equalityComparerDefaultProperty     = equalityComparerTypeForPropertyType.GetTypeInfo().GetProperty("Default");
            var getter = equalityComparerDefaultProperty.GetMethod;
            var equalityComparerExpressionObject     = getter.Invoke(null, null);
            var equalityComparerExpressionObjectType = equalityComparerExpressionObject.GetType();
            var equalityComparerExpression           = equalityComparerExpressionObjectType.GetTypeInfo().GetMethod("GetEqualsExpr").Invoke(equalityComparerExpressionObject, null);
            var hashCodeExpression        = equalityComparerExpressionObjectType.GetTypeInfo().GetMethod("GetGetHashCodeExpr").Invoke(equalityComparerExpressionObject, null);
            var inlinedEqualityExpression = ParameterInliner.Inline((LambdaExpression)equalityComparerExpression, Expression.PropertyOrField(left, pName), Expression.PropertyOrField(right, pName));
            var inlinedHashCodeExpression = ParameterInliner.Inline((LambdaExpression)hashCodeExpression, Expression.PropertyOrField(a, pName));

            return(Tuple.Create(inlinedEqualityExpression, inlinedHashCodeExpression));
        }
コード例 #5
0
ファイル: PivotExtensions.cs プロジェクト: yorek/Trill
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TInput"></typeparam>
        /// <typeparam name="TOutput"></typeparam>
        /// <typeparam name="TGroupKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <typeparam name="TAggValue"></typeparam>
        /// <typeparam name="TState"></typeparam>
        /// <param name="inputStreamable"></param>
        /// <param name="initializer"></param>
        /// <param name="keySelector"></param>
        /// <param name="attributeSelector"></param>
        /// <param name="valueSelector"></param>
        /// <param name="aggregate"></param>
        /// <returns></returns>
        public static IStreamable <TKey, TOutput> Pivot <TKey, TInput, TOutput, TGroupKey, TValue, TAggValue, TState>(
            this IStreamable <TKey, TInput> inputStreamable,
            Expression <Func <TOutput> > initializer,
            Expression <Func <TInput, TGroupKey> > keySelector,
            Expression <Func <TInput, string> > attributeSelector,
            Expression <Func <TInput, TValue> > valueSelector,
            Func <Window <CompoundGroupKey <TKey, TGroupKey>, TValue>, IAggregate <TValue, TState, TAggValue> > aggregate) where TOutput : new()
        {
            bool sourceHasNullableValues = IsNullable(typeof(TValue));

            if (initializer == null)
            {
                throw new ArgumentNullException(nameof(initializer));
            }

            var window             = new Window <CompoundGroupKey <TKey, TGroupKey>, TValue>(inputStreamable.Properties.GroupNested(keySelector).Select <TValue>(valueSelector, false, false));
            var agg                = aggregate(window);
            var valueAgg           = agg.TransformInput(valueSelector);
            var outputPublicFields =
                typeof(TOutput).GetTypeInfo()
                .GetFields(BindingFlags.Public | BindingFlags.Instance)
                .Select(f => Tuple.Create(f.Name, f.FieldType, (MemberInfo)f, !sourceHasNullableValues && IsNullable(f.FieldType)))
                .Concat(
                    typeof(TOutput).GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Where(p => p.GetIndexParameters().Length == 0)
                    .Select(f => Tuple.Create(f.Name, f.PropertyType, (MemberInfo)f, !sourceHasNullableValues && IsNullable(f.PropertyType))))
                .Where(m => m.Item2.GetTypeInfo().IsAssignableFrom(typeof(TAggValue))).ToArray();
            var aggArray = outputPublicFields.Select(
                m => valueAgg.ApplyFilter(
                    Expression.Lambda <Func <TInput, bool> >(
                        Expression.Equal(attributeSelector.Body, Expression.Constant(m.Item1)),
                        attributeSelector.Parameters)));

            var initialState = Expression.Lambda <Func <TState[]> >(Expression.NewArrayInit(typeof(TState), aggArray.Select(a => a.InitialState().Body)));

            var state       = Expression.Parameter(typeof(TState[]), "state");
            var time        = Expression.Parameter(typeof(long), "time");
            var input       = Expression.Parameter(typeof(TInput), "input");
            var accumulator = Expression.Lambda <Func <TState[], long, TInput, TState[]> >(
                Expression.NewArrayInit(
                    typeof(TState),
                    aggArray.Select((a, i) => ParameterInliner.Inline(a.Accumulate(), Expression.ArrayIndex(state, Expression.Constant(i)), time, input))), state, time, input);
            var deaccumulator = Expression.Lambda <Func <TState[], long, TInput, TState[]> >(
                Expression.NewArrayInit(
                    typeof(TState),
                    aggArray.Select((a, i) => ParameterInliner.Inline(a.Deaccumulate(), Expression.ArrayIndex(state, Expression.Constant(i)), time, input))), state, time, input);

            var state1     = Expression.Parameter(typeof(TState[]), "state1");
            var state2     = Expression.Parameter(typeof(TState[]), "state2");
            var difference = Expression.Lambda <Func <TState[], TState[], TState[]> >(
                Expression.NewArrayInit(
                    typeof(TState),
                    aggArray.Select((a, i) => ParameterInliner.Inline(a.Difference(), Expression.ArrayIndex(state1, Expression.Constant(i)), Expression.ArrayIndex(state1, Expression.Constant(i))))), state1, state2);

            var resultSelector = Expression.Lambda <Func <TState[], TAggValue[]> >(
                Expression.NewArrayInit(
                    typeof(TAggValue),
                    aggArray.Select((a, i) => ParameterInliner.Inline(a.ComputeResult(), Expression.ArrayIndex(state1, Expression.Constant(i))))), state1);
            var newAgg = new GeneratedAggregate <TInput, TState[], TAggValue[]>(initialState, accumulator, deaccumulator, difference, resultSelector);

            if (initializer.Body as NewExpression == null)
            {
                throw new ArgumentException("Initializer must return a constructor expression.", nameof(initializer));
            }

            var groupkey       = Expression.Parameter(typeof(GroupSelectorInput <TGroupKey>), "groupkey");
            var aggvalues      = Expression.Parameter(typeof(TAggValue[]), "aggvalue");
            var keyAssignments = new List <MemberAssignment>();

            // Key selector magic!
            switch (keySelector.Body.NodeType)
            {
            case ExpressionType.MemberAccess:
            {
                var selector = keySelector.Body as MemberExpression;
                if (selector.Expression.NodeType == ExpressionType.Parameter)
                {
                    keyAssignments.Add(Expression.Bind(
                                           typeof(TOutput).GetTypeInfo().GetMember(selector.Member.Name).Single(),
                                           Expression.PropertyOrField(groupkey, "Key")));
                }
                else
                {
                    throw new NotImplementedException();
                }
                break;
            }

            case ExpressionType.MemberInit:
            {
                var memberInit = keySelector.Body as MemberInitExpression;
                foreach (var init in memberInit.Bindings)
                {
                    if (init.BindingType != MemberBindingType.Assignment)
                    {
                        throw new NotImplementedException();
                    }
                    var assign = init as MemberAssignment;
                    if (assign.Expression is MemberExpression rightSide && rightSide.Expression.NodeType == ExpressionType.Parameter)
                    {
                        keyAssignments.Add(Expression.Bind(
                                               typeof(TOutput).GetTypeInfo().GetMember(assign.Member.Name).Single(),
                                               Expression.PropertyOrField(Expression.PropertyOrField(groupkey, "Key"), rightSide.Member.Name)));
                    }