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); } } } } }
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); } } }
public RulePathQualifier(string name, RulePathQualifier next) { this.name = name; this.next = next; }
internal override void AnalyzeUsage(CodeExpression expression, RuleAnalysis analysis, bool isRead, bool isWritten, RulePathQualifier qualifier) { ruleExpr.AnalyzeUsage(analysis, isRead, isWritten, qualifier); }
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); }