コード例 #1
0
        /// <summary>
        /// Analyzes the method call expression provided as parameter and
        /// returns an appropiated member access.
        /// </summary>
        /// <param name="methodCall">
        /// The method call to analyze.
        /// </param>
        /// <param name="context">
        /// Current context.
        /// </param>
        /// <returns>
        /// A System.Linq.Expressions.Expression.
        /// </returns>
        protected override Expression VisitMethodCall(MethodCallExpression methodCall, QueryContext context)
        {
            // note that we are not skipping any MethodCalls
            var e = new MethodCallVisitEventArgs(methodCall);

            // throwing away or replacing this method call if any interceptor found
            if (this.ExtensionsProvider.OnMethodCallVisit(e, context))
            {
                if (e.SubstituteExpression != e.MethodCall)
                {
                    return(this.Visit(e.SubstituteExpression, context));
                }
            }

            return(base.VisitMethodCall(methodCall, context));
        }
コード例 #2
0
        /// <summary>
        /// Handles the MethodCallVisit event.
        /// </summary>
        /// <param name="e">
        /// The <see cref="LogicSoftware.DataAccess.Repository.Extended.Events.MethodCallVisitEventArgs"/> instance containing the event data.
        /// </param>
        public override void OnMethodCallVisit(MethodCallVisitEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            if (e.MethodCall.Method.DeclaringType == typeof(ProjectionExtensions))
            {
                var sourceQueryExpression = e.MethodCall.Arguments.First();
                var projectionConfig      = e.MethodCall.Arguments.Count == 2
                                           ? ((ConstantExpression)e.MethodCall.Arguments.Last()).Value
                                           : null;
                var projectionType = projectionConfig != null
                                         ? projectionConfig.GetType()
                                         : TypeSystem.GetElementType(e.MethodCall.Type);

                e.SubstituteExpression = this.ApplySequenceProjection(sourceQueryExpression, projectionType, projectionConfig);
            }
        }
コード例 #3
0
        /// <summary>
        /// Notifies interceptors about MethodCallVisit stage in query execution.
        /// </summary>
        /// <param name="e">
        /// The <see cref="LogicSoftware.DataAccess.Repository.Extended.Events.MethodCallVisitEventArgs"/> instance containing the event data.
        /// </param>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// <c>true</c>, if method call was interepted, <c>false</c> otherwise.
        /// </returns>
        public bool OnMethodCallVisit(MethodCallVisitEventArgs e, QueryContext context)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            // checking if this method call visit must be intercepted

            // getting interceptor that subscibed to this method call visit
            // allowing to specify InterceptVisitAttribute for all methods in class
            // todo: add caching?
            InterceptVisitAttribute attribute = e.MethodCall.Method.GetCustomAttributes <InterceptVisitAttribute>().SingleOrDefault()
                                                ?? e.MethodCall.Method.DeclaringType.GetCustomAttributes <InterceptVisitAttribute>().SingleOrDefault();

            // no suitable interceptors found
            if (attribute == null)
            {
                return(false);
            }

            // get from dictionary or create new
            IQueryInterceptor interceptor;

            if (!context.Interceptors.TryGetValue(attribute.InterceptorType, out interceptor))
            {
                interceptor = this.AddInterceptorToContext(attribute.InterceptorType, context);
            }

            // intercept
            interceptor.OnMethodCallVisit(e);

            return(true);
        }
コード例 #4
0
        public override void OnMethodCallVisit(MethodCallVisitEventArgs e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            // working with static extension methods with one "this" argument and with instance methods with no arguments
            // todo: methods with multiple arguments can be implemented too
            // todo: maybe better check?
            if ((e.MethodCall.Method.IsStatic && e.MethodCall.Arguments.Count == 1) ||
                (!e.MethodCall.Method.IsStatic && e.MethodCall.Arguments.Count == 0))
            {
                var expressionAttribute = (ExpandWithExpressionAttribute)e.MethodCall.Method.GetCustomAttributes(typeof(ExpandWithExpressionAttribute), false).SingleOrDefault();

                if (expressionAttribute == null)
                {
                    throw new InvalidOperationException(String.Format(
                                                            CultureInfo.InvariantCulture,
                                                            "Method '{0}' in '{1}' class has no ExpandWithExpression attribute.",
                                                            e.MethodCall.Method.Name,
                                                            e.MethodCall.Method.DeclaringType.Name));
                }

                var declaringType = expressionAttribute.DeclaringType ?? e.MethodCall.Method.DeclaringType;
                var methodName    = expressionAttribute.MethodName ?? e.MethodCall.Method.Name;

                var expressionMethodInfo = declaringType.GetMethod(
                    methodName,
                    BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);

                if (expressionMethodInfo == null)
                {
                    throw new ArgumentException(String.Format(
                                                    CultureInfo.InvariantCulture,
                                                    "Method specified in ExpandWithExpression attribute of '{0}' method in '{1}' class is not found.",
                                                    e.MethodCall.Method.Name,
                                                    e.MethodCall.Method.DeclaringType.Name));
                }

                var customExpandedExpression = (LambdaExpression)expressionMethodInfo.Invoke(null, new object[] { this.Scope });

                // parameterExpression is object in case of instance method or single (todo: first) argument in case of extension method
                var parameterExpression = e.MethodCall.Method.IsStatic ? e.MethodCall.Arguments.Single() : e.MethodCall.Object;

                // validating custom expanded expression
                if (customExpandedExpression.Parameters.Single().Type != parameterExpression.Type ||
                    customExpandedExpression.Body.Type != e.MethodCall.Type)
                {
                    throw new InvalidOperationException(String.Format(
                                                            CultureInfo.InvariantCulture,
                                                            "Method '{0}' in '{1}' class returns invalid expression.",
                                                            expressionMethodInfo.Name,
                                                            expressionMethodInfo.DeclaringType.Name));
                }

                // localize expression (replace its parameter with local object expression)
                var localizedCustomExpandedExpression = new ExpressionParameterReplacer(
                    customExpandedExpression.Parameters.Single(),
                    parameterExpression)
                                                        .Visit(customExpandedExpression.Body);

                e.SubstituteExpression = localizedCustomExpandedExpression;
            }
        }
コード例 #5
0
ファイル: QueryInterceptor.cs プロジェクト: hafei/lsda
 /// <summary>
 /// The MethodCallVisit stage handler.
 /// </summary>
 /// <param name="e">
 /// The <see cref="LogicSoftware.DataAccess.Repository.Extended.Events.MethodCallVisitEventArgs"/> instance containing the event data.
 /// </param>
 /// <remarks>
 /// Base implementation is empty.
 /// </remarks>
 public virtual void OnMethodCallVisit(MethodCallVisitEventArgs e)
 {
 }