/*Throws an exception if single method is not found.*/ private MethodInfo GetMethodInfoInClassOrParents([NotNull] string methodName, [NotNull, ItemNotNull] Type[] parameterTypes) { StringBuilder errorMessage; var matchedMethodInfos = new List <MethodInfo>(); MethodInfo findMethodInfoInType(Type type) { foreach (var methodInfo in type.GetMethods()) { if (Helpers.IsMethodAMatch(methodInfo, methodName, parameterTypes) && methodInfo.ReturnType == ValueTypeInfo.Type) { return(methodInfo); } } return(null); } void appendMethodParametersDescriptionOnInvalidSignature() { var parametersStrBldr = new StringBuilder(); parametersStrBldr.Append("Method parameters used for lookup are: "); if (parameterTypes.Length == 0) { parametersStrBldr.AppendLine("no parameters."); } else { parametersStrBldr.AppendLine(string.Join(", ", MethodSignatureElement.Parameters.Select(x => x.ValueTypeInfo.TypeCSharpFullName))); } errorMessage.AppendLine(parametersStrBldr.ToString()); errorMessage.AppendLine("Note, currently methods that use in, ref, out keywords are not considered."); } if (DeclaringTypeInfoInAttribute != null) { var matchedMethodInfo = findMethodInfoInType(DeclaringTypeInfoInAttribute.Type); if (matchedMethodInfo != null) { return(matchedMethodInfo); } errorMessage = new StringBuilder(); errorMessage.AppendFormat("Method named '{0}', with return type '{1}' and the specified parameters was not found in interface '{2}', specified in attribute '{3}'.", methodName, ValueTypeInfo.TypeCSharpFullName, DeclaringTypeInfoInAttribute.TypeCSharpFullName, ConfigurationFileAttributeNames.DeclaringInterface); errorMessage.AppendLine(); appendMethodParametersDescriptionOnInvalidSignature(); errorMessage.AppendLine("Remove the attribute to look in auto-implemented interface, and all the base interfaces."); throw new ConfigurationParseException(this, errorMessage.ToString()); } void processType(Type type, ref bool stopProcessing2) { var methodInfo = findMethodInfoInType(type); if (methodInfo != null) { matchedMethodInfos.Add(methodInfo); if (type == ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.Type) { stopProcessing2 = true; } } } var stopProcessing = false; TypeMemberLookupHelper.ProcessTypeImplementedInterfacesAndBaseTypes( ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.Type, processType, ref stopProcessing); if (matchedMethodInfos.Count == 1) { return(matchedMethodInfos[0]); } errorMessage = new StringBuilder(); errorMessage.AppendFormat("Method with name '{0}', with return type '{1}' and the specified parameters ", methodName, ValueTypeInfo.TypeCSharpFullName); if (matchedMethodInfos.Count == 0) { errorMessage.AppendFormat("was not found in auto-generated interface '{0}' or any of its parents.", ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.TypeCSharpFullName); errorMessage.AppendLine(); appendMethodParametersDescriptionOnInvalidSignature(); } else { errorMessage.AppendFormat("was not found in auto-generated interface '{0}', however a method with this name, signature, and return type occurs multiple times in parents of interface '{0}'.", ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.TypeCSharpFullName); errorMessage.AppendLine(); errorMessage.AppendLine($"Please use attribute '{ConfigurationFileAttributeNames.DeclaringInterface}', to explicitly specify the type, where the auto-implemented method is declared."); //--Example of proxy service-- errorMessage.AppendFormat($"Note, if necessary, you can use '{0}' to proxy the service '{1}'.", ConfigurationFileElementNames.ProxyService, ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.TypeCSharpFullName); errorMessage.AppendLine(); errorMessage.AppendLine(MessagesHelper.GenerateProxyServiceExample(matchedMethodInfos[0].DeclaringType, ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.Type)); // List of parent types appendMethodParametersDescriptionOnInvalidSignature(); errorMessage.AppendLine( string.Format("The following is the list of interfaces, where the method was found: {0}", string.Join(", ", matchedMethodInfos.Select(x => x.DeclaringType.GetTypeNameInCSharpClass())))); } throw new ConfigurationParseException(this, errorMessage.ToString()); }
public ClassMemberData GetClassMemberData(IConfigurationFileElement configurationFileElement, string classMemberPath, IEnumerable <IParameter> parameters) { ITypeInfo classInfo = null; ITypeInfo memberTypeInfo; string classMemberName = null; Type[] parameterTypes = parameters.Select(x => x.ValueTypeInfo.Type).ToArray(); var allMatchedMemberInfos = new List <MemberInfo>(); var isStaticMember = true; var classMemberCategory = ClassMemberCategory.Field; var lastIndexofDot = classMemberPath.LastIndexOf('.'); if (lastIndexofDot > 0 && lastIndexofDot + 1 < classMemberPath.Length) { classMemberName = classMemberPath.Substring(lastIndexofDot + 1).Trim(); } if (string.IsNullOrEmpty(classMemberName)) { throw new ConfigurationParseException(configurationFileElement, $"No class member is specified in '{classMemberPath}'. {ExamplesOfValidClassPaths}"); } var typeFullName = classMemberPath.Substring(0, lastIndexofDot).Trim(); if (typeFullName.Length == 0) { throw new ConfigurationParseException(configurationFileElement, $"No class name is provided in {classMemberPath}. {ExamplesOfValidClassPaths}"); } INamedTypeDefinitionElement namedTypeDefinitionElement = null; if (!typeFullName.Contains(".")) { namedTypeDefinitionElement = configurationFileElement.GetTypeDefinition(typeFullName); if (namedTypeDefinitionElement != null) { classInfo = namedTypeDefinitionElement.ValueTypeInfo; _pluginAssemblyTypeUsageValidator.Validate(configurationFileElement, classInfo); } } if (classInfo == null) { classInfo = _typeHelper.GetTypeInfoFromTypeFullName(configurationFileElement, typeFullName); } if (classInfo.Type.IsEnum) { if (classInfo.Type.GetEnumNames().FirstOrDefault(x => classMemberName.Equals(x, StringComparison.Ordinal)) == null) { throw new ConfigurationParseException(configurationFileElement, $"Enumeration value '{classMemberName}' is not defined in enumeration '{classInfo.TypeCSharpFullName}'."); } allMatchedMemberInfos.Add(classInfo.Type.GetMember(classMemberName).First()); classMemberCategory = ClassMemberCategory.EnumValue; isStaticMember = true; memberTypeInfo = classInfo; } else { Type memberReturnType = null; void processType(Type type, ref bool stopProcessingParam) { MemberInfo memberInfo = null; try { if (parameterTypes.Length > 0) { // Lets try to find a method first. var methodInfo = type.GetMethods().FirstOrDefault(x => Helpers.IsMethodAMatch(x, classMemberName, parameterTypes)); if (methodInfo != null) { memberInfo = methodInfo; classMemberCategory = ClassMemberCategory.Method; isStaticMember = methodInfo.IsStatic; memberReturnType = methodInfo.ReturnType; } return; } var memberInfos = type.GetMembers().Where(x => classMemberName.Equals(x.Name, StringComparison.Ordinal)).ToList(); if (memberInfos.Count == 0) { return; } if (memberInfos[0] is MethodInfo) { var methodInfo = (MethodInfo)memberInfos.FirstOrDefault(x => x is MethodInfo methodInfo2 && methodInfo2.IsPublic && methodInfo2.GetParameters().Length == 0); if (methodInfo == null) { return; } memberInfo = methodInfo; classMemberCategory = ClassMemberCategory.Method; isStaticMember = methodInfo.IsStatic; memberReturnType = methodInfo.ReturnType; } else { memberInfo = memberInfos[0]; if (memberInfo is FieldInfo fieldInfo) { if (!fieldInfo.IsPublic) { return; } classMemberCategory = ClassMemberCategory.Field; isStaticMember = fieldInfo.IsStatic || fieldInfo.IsLiteral; memberReturnType = fieldInfo.FieldType; } else if (memberInfo is PropertyInfo propertyInfo) { var getMethod = propertyInfo.GetGetMethod(); if (!getMethod.IsPublic) { return; } classMemberCategory = ClassMemberCategory.Property; isStaticMember = getMethod.IsStatic; memberReturnType = getMethod.ReturnType; } } } finally { if (memberInfo != null) { allMatchedMemberInfos.Add(memberInfo); if (type == classInfo.Type) { stopProcessingParam = true; } } } } var stopProcessing = false; _typeMemberLookupHelper.ProcessTypeImplementedInterfacesAndBaseTypes(classInfo.Type, processType, ref stopProcessing); if (allMatchedMemberInfos.Count == 1) { memberTypeInfo = _typeHelper.GetTypeInfoFromType(configurationFileElement, memberReturnType); } else { var errorMessage = new StringBuilder(); errorMessage.AppendFormat("Member with name '{0}'", classMemberName); if (parameterTypes.Length > 0) { errorMessage.AppendFormat(" and parameters of types: ({0})", string.Join(",", parameters.Select(x => x.ValueTypeInfo.TypeCSharpFullName))); } else { errorMessage.Append(" and zero parameters"); } if (allMatchedMemberInfos.Count == 0) { errorMessage.AppendFormat(" was not found in type '{0}' or any of its parents.", classInfo.TypeCSharpFullName); errorMessage.AppendLine(); } else { errorMessage.AppendFormat(" was not found in type '{0}', however a member with this name occurs multiple times in parents of type '{0}'.", classInfo.TypeCSharpFullName); errorMessage.AppendLine(); errorMessage.AppendLine("Please specify one of the parent types where the member is declared."); errorMessage.AppendFormat($"Note, if necessary, you can use '{0}' to proxy the service '{1}'.", ConfigurationFileElementNames.ProxyService, classInfo.TypeCSharpFullName); errorMessage.AppendLine(); errorMessage.AppendLine(MessagesHelper.GenerateProxyServiceExample(allMatchedMemberInfos[0].DeclaringType, classInfo.Type)); errorMessage.AppendLine( string.Format("The following is the list of types, where the member named '{0}' was found: {1}", classMemberName, string.Join(", ", allMatchedMemberInfos.Select(x => x.DeclaringType.GetTypeNameInCSharpClass())))); } throw new ConfigurationParseException(configurationFileElement, errorMessage.ToString()); } } return(new ClassMemberData(classInfo, memberTypeInfo, allMatchedMemberInfos[0], parameters, !isStaticMember, classMemberCategory)); }
/*Throws an exception if single method is not found.*/ private PropertyInfo GetPropertyInfoInClassOrParents([NotNull] string propertyName) { StringBuilder errorMessage; var matchedPropertyInfos = new List <PropertyInfo>(); PropertyInfo findPropertyInfoInType(Type type) { foreach (var propertyInfo in type.GetProperties()) { if (!propertyInfo.Name.Equals(propertyName, StringComparison.Ordinal)) { continue; } var getMethodInfo = propertyInfo.GetMethod; if (getMethodInfo != null && getMethodInfo.IsPublic && getMethodInfo.ReturnType == ValueTypeInfo.Type) { return(propertyInfo); } } return(null); } if (DeclaringTypeInfoInAttribute != null) { var matchedPropertyInfo = findPropertyInfoInType(DeclaringTypeInfoInAttribute.Type); if (matchedPropertyInfo != null) { return(matchedPropertyInfo); } errorMessage = new StringBuilder(); errorMessage.AppendFormat("Property named '{0}', and with return type '{1}' was not found in interface '{2}', specified in attribute '{3}'.", propertyName, ValueTypeInfo.TypeCSharpFullName, DeclaringTypeInfoInAttribute.TypeCSharpFullName, ConfigurationFileAttributeNames.DeclaringInterface); errorMessage.AppendLine(); errorMessage.AppendLine("Remove the attribute to look in auto-implemented interface, and all the base interfaces."); throw new ConfigurationParseException(this, errorMessage.ToString()); } void processType(Type type, ref bool stopProcessing2) { var propertyInfo = findPropertyInfoInType(type); if (propertyInfo != null) { matchedPropertyInfos.Add(propertyInfo); if (type == ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.Type) { stopProcessing2 = true; } } } var stopProcessing = false; TypeMemberLookupHelper.ProcessTypeImplementedInterfacesAndBaseTypes( ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.Type, processType, ref stopProcessing); if (matchedPropertyInfos.Count == 1) { return(matchedPropertyInfos[0]); } errorMessage = new StringBuilder(); errorMessage.AppendFormat("Property with name '{0}', and with return type '{1}' ", propertyName, ValueTypeInfo.TypeCSharpFullName); if (matchedPropertyInfos.Count == 0) { errorMessage.AppendFormat("was not found in auto-generated interface '{0}' or any of its parents.", ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.TypeCSharpFullName); errorMessage.AppendLine(); } else { errorMessage.AppendFormat("was not found in auto-generated interface '{0}', however a property with this name and return type occurs multiple times in parents of interface '{0}'.", ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.TypeCSharpFullName); errorMessage.AppendLine(); errorMessage.AppendLine($"Please use attribute '{ConfigurationFileAttributeNames.DeclaringInterface}', to explicitly specify the type, where the auto-implemented property is declared."); //--Example of proxy service-- errorMessage.AppendFormat($"Note, if necessary, you can use '{0}' to proxy the service '{1}'.", ConfigurationFileElementNames.ProxyService, ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.TypeCSharpFullName); errorMessage.AppendLine(); errorMessage.AppendLine(MessagesHelper.GenerateProxyServiceExample(matchedPropertyInfos[0].DeclaringType, ParentAutoGeneratedServiceElement.ImplementedInterfaceTypeInfo.Type)); // List of parent types errorMessage.AppendLine( string.Format("The following is the list of interfaces, where the property was found: {0}", string.Join(", ", matchedPropertyInfos.Select(x => x.DeclaringType.GetTypeNameInCSharpClass())))); } throw new ConfigurationParseException(this, errorMessage.ToString()); }