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(); } } }
private bool ValidateInvokeAttribute(RuleValidation validation, MemberInfo member, Type contextType, Stack <MemberInfo> methodStack) { string message; ValidationError error; if (string.IsNullOrEmpty(methodInvoked)) { // Invoked method or property name was null or empty. message = string.Format(CultureInfo.CurrentCulture, Messages.AttributeMethodNotFound, member.Name, this.GetType().Name, Messages.NullValue); error = new ValidationError(message, ErrorNumbers.Warning_RuleAttributeNoMatch, true); error.UserData[RuleUserDataKeys.ErrorObject] = this; validation.AddError(error); return(false); } bool valid = true; // 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); if (members == null || members.Length == 0) { // Invoked method or property didn't exist. message = string.Format(CultureInfo.CurrentCulture, Messages.AttributeMethodNotFound, member.Name, this.GetType().Name, methodInvoked); error = new ValidationError(message, ErrorNumbers.Warning_RuleAttributeNoMatch, true); error.UserData[RuleUserDataKeys.ErrorObject] = this; validation.AddError(error); valid = false; } else { for (int i = 0; i < members.Length; ++i) { MemberInfo mi = members[i]; if (!methodStack.Contains(mi)) // Prevent recursion { methodStack.Push(mi); object[] attrs = mi.GetCustomAttributes(typeof(RuleAttribute), true); if (attrs != null && attrs.Length != 0) { foreach (RuleAttribute invokedRuleAttr in attrs) { if (invokedRuleAttr is RuleReadWriteAttribute readWriteAttr) { // This read/write attribute may not specify a target of "Parameter", since // we can't map from the invoker's parameters to the invokee's parameters. if (readWriteAttr.Target == RuleAttributeTarget.Parameter) { message = string.Format(CultureInfo.CurrentCulture, Messages.InvokeAttrRefersToParameterAttribute, mi.Name); error = new ValidationError(message, ErrorNumbers.Error_InvokeAttrRefersToParameterAttribute, true); error.UserData[RuleUserDataKeys.ErrorObject] = this; validation.AddError(error); valid = false; } else { // Validate the read/write attribute normally. readWriteAttr.Validate(validation, mi, contextType, null); } } else { RuleInvokeAttribute invokeAttr = (RuleInvokeAttribute)invokedRuleAttr; invokeAttr.ValidateInvokeAttribute(validation, mi, contextType, methodStack); } } } methodStack.Pop(); } } } return(valid); }