Example #1
0
        public ITypeInfo GetTypeInfo(IConfigurationFileElement requestingConfigurationFileElement, string typeAttributeName, string assemblyAttributeName,
                                     string typeRefAttributeName, IEnumerable <ITypeInfo> genericTypeParameters)
        {
            ITypeInfo tryGetKnownTypeInfo()
            {
                // Lets have this in a block, so that typeInfo is not accessible in the rst of the code.
                if (TryGetPrimitiveType(requestingConfigurationFileElement, out var typeInfo))
                {
                    return(typeInfo);
                }

                if (requestingConfigurationFileElement.HasAttribute(typeRefAttributeName))
                {
                    if (requestingConfigurationFileElement.HasAttribute(typeAttributeName) || requestingConfigurationFileElement.HasAttribute(assemblyAttributeName))
                    {
                        throw new ConfigurationParseException(requestingConfigurationFileElement, $"Attributes '{typeAttributeName}' and '{assemblyAttributeName}' cannot be used to specify a type, if attribute '{typeRefAttributeName}' is used.");
                    }

                    var typeRefAttributeValue = requestingConfigurationFileElement.GetAttributeValue(typeRefAttributeName);

                    var typeDefinition = requestingConfigurationFileElement.GetTypeDefinition(typeRefAttributeValue);
                    if (typeDefinition?.ValueTypeInfo == null)
                    {
                        throw new ConfigurationParseException(requestingConfigurationFileElement, $"Invalid value of attribute '{typeRefAttributeName}'. Type definition with alias '{typeRefAttributeValue}' was not found in section '{ConfigurationFileElementNames.TypeDefinitions}'.");
                    }

                    return(typeDefinition?.ValueTypeInfo);
                }

                return(null);
            }

            var typeInfo2 = tryGetKnownTypeInfo();

            if (typeInfo2 != null)
            {
                _pluginAssemblyTypeUsageValidator.Validate(requestingConfigurationFileElement, typeInfo2);
                return(typeInfo2);
            }

            if (!requestingConfigurationFileElement.HasAttribute(typeAttributeName))
            {
                throw new ConfigurationParseException(requestingConfigurationFileElement,
                                                      $"A value for either '{typeRefAttributeName}' or '{typeAttributeName}' should be provided. If attribute '{typeAttributeName}' is present, an optional attribute '{assemblyAttributeName}' value can be provided as well, to enforce that the type is in specified assembly.");
            }

            var typeAttributeValue = requestingConfigurationFileElement.GetAttributeValue <string>(typeAttributeName);

            return(GetTypeInfoFromTypeFullName(requestingConfigurationFileElement, typeAttributeValue, genericTypeParameters, typeAttributeValue, assemblyAttributeName));
        }
Example #2
0
        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));
        }