private void ReplaceTypRefAttributeWithTypeAndAssembly([NotNull] XmlElement xmlElement, ConfigurationFileMutationType configurationFileMutationType) { if (configurationFileMutationType == ConfigurationFileMutationType.None) { return; } string typeRefAttributeName = null; string typeAttributeName = null; var assemblyAttributeName = ConfigurationFileAttributeNames.Assembly; if (xmlElement.HasAttribute(ConfigurationFileAttributeNames.TypeRef)) { typeRefAttributeName = ConfigurationFileAttributeNames.TypeRef; typeAttributeName = ConfigurationFileAttributeNames.Type; } else if (xmlElement.HasAttribute(ConfigurationFileAttributeNames.InterfaceRef)) { typeRefAttributeName = ConfigurationFileAttributeNames.InterfaceRef; typeAttributeName = ConfigurationFileAttributeNames.Interface; } else if (xmlElement.HasAttribute(ConfigurationFileAttributeNames.SerializerAggregatorTypeRef)) { typeRefAttributeName = ConfigurationFileAttributeNames.SerializerAggregatorTypeRef; typeAttributeName = ConfigurationFileAttributeNames.SerializerAggregatorType; } if (typeRefAttributeName == null) { return; } var elementPath = GetElementPath(xmlElement); LogHelper.Context.Log.Info($"Started mutating element '{elementPath}'."); INamedTypeDefinitionElement namedTypeDefinitionElement = null; var typeRefAttributeValue = xmlElement.GetAttribute(typeRefAttributeName); xmlElement.RemoveAttribute(typeRefAttributeName); { var currentXmlElement = xmlElement; while (currentXmlElement != null && !currentXmlElement.Name.Equals("iocConfiguration", StringComparison.Ordinal)) { if (currentXmlElement.Name.Equals(ConfigurationFileElementNames.PluginSetup)) { if (currentXmlElement.GetAttribute(ConfigurationFileAttributeNames.Plugin).Equals(Plugin1Name)) { namedTypeDefinitionElement = _pluginTypeDefinitionsElement.GetTypeDefinition(typeRefAttributeValue); break; } Assert.Fail("Test only Plugin1"); } currentXmlElement = currentXmlElement.ParentNode as XmlElement; } } if (namedTypeDefinitionElement == null) { namedTypeDefinitionElement = _typeDefinitionsElement.GetTypeDefinition(typeRefAttributeValue); } Assert.IsNotNull(namedTypeDefinitionElement); var typeFullNameInConfigFile = GetConfigStyleTypeName(namedTypeDefinitionElement); xmlElement.SetAttributeValue(typeAttributeName, typeFullNameInConfigFile); LogHelper.Context.Log.Info($"Mutated element '{elementPath}': The value of attribute {typeRefAttributeName}='{typeRefAttributeValue}' was replaced with attribute {typeAttributeName}='{typeFullNameInConfigFile}'"); if (configurationFileMutationType == ConfigurationFileMutationType.UseTypeAndAssembly) { xmlElement.SetAttributeValue(assemblyAttributeName, namedTypeDefinitionElement.ValueTypeInfo.Assembly.Alias); LogHelper.Context.Log.Info($"Mutated element '{elementPath}': Added attribute {assemblyAttributeName}='{namedTypeDefinitionElement.ValueTypeInfo.Assembly.Alias}'"); } }
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)); }