internal override void Analyze(RuleAnalysis analysis, MemberInfo member, CodeExpression targetExpression, RulePathQualifier targetQualifier, CodeExpressionCollection argumentExpressions, ParameterInfo[] parameters, List <CodeExpression> attributedExpressions)
        {
            Stack <MemberInfo> methodStack = new Stack <MemberInfo>();

            methodStack.Push(member);

            AnalyzeInvokeAttribute(analysis, member.DeclaringType, methodStack, targetExpression, targetQualifier, argumentExpressions, parameters, attributedExpressions);

            methodStack.Pop();
        }
        private void AnalyzeInvokeAttribute(RuleAnalysis analysis, Type contextType, Stack <MemberInfo> methodStack, CodeExpression targetExpression, RulePathQualifier targetQualifier, CodeExpressionCollection argumentExpressions, ParameterInfo[] parameters, List <CodeExpression> attributedExpressions)
        {
            // Go through all the methods and properties on the target context,
            // looking for all the ones that match the name on the attribute.
            MemberInfo[] members = contextType.GetMember(methodInvoked, MemberTypes.Method | MemberTypes.Property, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);

            for (int m = 0; m < members.Length; ++m)
            {
                MemberInfo mi = members[m];
                if (!methodStack.Contains(mi)) // Prevent recursion
                {
                    methodStack.Push(mi);

                    object[] attrs = mi.GetCustomAttributes(typeof(RuleAttribute), true);
                    if (attrs != null && attrs.Length != 0)
                    {
                        RuleAttribute[] ruleAttrs = (RuleAttribute[])attrs;
                        for (int i = 0; i < ruleAttrs.Length; ++i)
                        {
                            RuleAttribute ruleAttr = ruleAttrs[i];

                            if (ruleAttr is RuleReadWriteAttribute readWriteAttr)
                            {
                                // Just analyze the read/write attribute normally.
                                readWriteAttr.Analyze(analysis, mi, targetExpression, targetQualifier, argumentExpressions, parameters, attributedExpressions);
                            }
                            else
                            {
                                RuleInvokeAttribute invokeAttr = (RuleInvokeAttribute)ruleAttr;
                                invokeAttr.AnalyzeInvokeAttribute(analysis, contextType, methodStack, targetExpression, targetQualifier, argumentExpressions, parameters, attributedExpressions);
                            }
                        }
                    }

                    methodStack.Pop();
                }
            }
        }
 internal abstract void Analyze(RuleAnalysis analysis, MemberInfo member, CodeExpression targetExpression, RulePathQualifier targetQualifier, CodeExpressionCollection argumentExpressions, ParameterInfo[] parameters, List <CodeExpression> attributedExpressions);
        internal override void Analyze(RuleAnalysis analysis, MemberInfo member, CodeExpression targetExpression, RulePathQualifier targetQualifier, CodeExpressionCollection argumentExpressions, ParameterInfo[] parameters, List <CodeExpression> attributedExpressions)
        {
            // A RuleWrite attribute is only applicable if we're analyzing for writes.
            if (!analysis.ForWrites)
            {
                return;
            }

            base.AnalyzeReadWrite(analysis, targetExpression, targetQualifier, argumentExpressions, parameters, attributedExpressions);
        }
        internal void AnalyzeReadWrite(RuleAnalysis analysis, CodeExpression targetExpression, RulePathQualifier targetQualifier, CodeExpressionCollection argumentExpressions, ParameterInfo[] parameters, List <CodeExpression> attributedExpressions)
        {
            if (string.IsNullOrEmpty(attributePath))
            {
                // If the suffix is null or empty, this means the RuleAttributeTarget has no dependencies.
                if (attributeTarget == RuleAttributeTarget.This)
                {
                    // The target object has no dependencies.
                    attributedExpressions.Add(targetExpression);
                }
                else if (attributeTarget == RuleAttributeTarget.Parameter)
                {
                    // ALL arguments have no dependencies.
                    for (int i = 0; i < argumentExpressions.Count; ++i)
                    {
                        attributedExpressions.Add(argumentExpressions[i]);
                    }
                }
            }
            else
            {
                string suffix = attributePath;

                bool isRead  = !analysis.ForWrites;
                bool isWrite = analysis.ForWrites;

                if (attributeTarget == RuleAttributeTarget.This)
                {
                    // Target is "This", so perform the analysis on the target expression.

                    // Remove the optional "this/" token if present.
                    string optionalPrefix = "this/";
                    if (suffix.StartsWith(optionalPrefix, StringComparison.Ordinal))
                    {
                        suffix = suffix.Substring(optionalPrefix.Length);
                    }

                    RuleExpressionWalker.AnalyzeUsage(analysis, targetExpression, isRead, isWrite, new RulePathQualifier(suffix, targetQualifier));
                    attributedExpressions.Add(targetExpression);
                }
                else if (attributeTarget == RuleAttributeTarget.Parameter)
                {
                    string paramName = null;

                    int firstSlash = suffix.IndexOf('/');
                    if (firstSlash >= 0)
                    {
                        paramName = suffix.Substring(0, firstSlash);
                        suffix    = suffix.Substring(firstSlash + 1);
                    }
                    else
                    {
                        paramName = suffix;
                        suffix    = null;
                    }

                    // Find the ParameterInfo that corresponds to this attribute path.
                    ParameterInfo param = Array.Find <ParameterInfo>(parameters,
                                                                     delegate(ParameterInfo p) { return(p.Name == paramName); });
                    if (param != null)
                    {
                        RulePathQualifier qualifier = string.IsNullOrEmpty(suffix) ? null : new RulePathQualifier(suffix, null);

                        // 99.9% of the time, the parameter usage attribute only applies to one argument.  However,
                        // if this attribute corresponds to the last parameter, then just assume that all the trailing
                        // arguments correspond.  (In other words, if the caller passed more arguments then there
                        // are parameters, we assume it was a params array.)
                        //
                        // Usually this loop will only execute once.
                        int end = param.Position + 1;
                        if (param.Position == parameters.Length - 1)
                        {
                            end = argumentExpressions.Count;
                        }

                        for (int i = param.Position; i < end; ++i)
                        {
                            CodeExpression argExpr = argumentExpressions[i];
                            RuleExpressionWalker.AnalyzeUsage(analysis, argExpr, isRead, isWrite, qualifier);
                            attributedExpressions.Add(argExpr);
                        }
                    }
                }
            }
        }
예제 #6
0
 internal void AnalyzeRuleAttributes(MemberInfo member, CodeExpression targetExpr, RulePathQualifier targetQualifier, CodeExpressionCollection argExprs, ParameterInfo[] parameters, List <CodeExpression> attributedExprs)
 {
     object[] attrs = member.GetCustomAttributes(typeof(RuleAttribute), true);
     if (attrs != null && attrs.Length > 0)
     {
         RuleAttribute[] ruleAttrs = (RuleAttribute[])attrs;
         for (int i = 0; i < ruleAttrs.Length; ++i)
         {
             ruleAttrs[i].Analyze(this, member, targetExpr, targetQualifier, argExprs, parameters, attributedExprs);
         }
     }
 }
예제 #7
0
 public RulePathQualifier(string name, RulePathQualifier next)
 {
     this.name = name;
     this.next = next;
 }
예제 #8
0
 internal override void AnalyzeUsage(CodeExpression expression, RuleAnalysis analysis, bool isRead, bool isWritten, RulePathQualifier qualifier)
 {
     ruleExpr.AnalyzeUsage(analysis, isRead, isWritten, qualifier);
 }
예제 #9
0
        public static void AnalyzeUsage(RuleAnalysis analysis, CodeExpression expression, bool isRead, bool isWritten, RulePathQualifier qualifier)
        {
            if (analysis == null)
            {
                throw new ArgumentNullException("analysis");
            }

            RuleExpressionInternal ruleExpr = GetExpression(expression);

            ruleExpr.AnalyzeUsage(expression, analysis, isRead, isWritten, qualifier);
        }