예제 #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));
        }
예제 #2
0
        internal static T GetAttributeEnumValue <T>(this IConfigurationFileElement configurationFileElement, string attributeName) where T : struct
        {
            var typeOfT = typeof(T);

            if (!typeOfT.IsEnum)
            {
                throw new ConfigurationParseException(configurationFileElement, $"Type '{typeOfT.FullName}' is not an enum type.");
            }

            var attributeValue = configurationFileElement.GetAttributeValue(attributeName)?.Trim();

            if (attributeValue == null)
            {
                attributeValue = string.Empty;
            }

            if (attributeValue.Length > 0)
            {
                string attributeValueCapitalized;

                if (attributeValue.Length == 1)
                {
                    attributeValueCapitalized = attributeValue.ToUpper();
                }
                else
                {
                    attributeValueCapitalized = $"{char.ToUpper(attributeValue[0])}{attributeValue.Substring(1)}";
                }

                if (Enum.TryParse <T>(attributeValueCapitalized, out var enumValue))
                {
                    return(enumValue);
                }
            }

            throw new ConfigurationParseException(configurationFileElement, $"Could not parse value '{attributeValue}' to an enum value of type '{typeof(T).FullName}'.");
        }
예제 #3
0
 /// <summary>
 /// </summary>
 /// <param name="configurationFileElement"></param>
 /// <exception cref="ConfigurationParseException">Throws this exception if the attribute value is null or empty string.</exception>
 internal static string GetNameAttributeValue(this IConfigurationFileElement configurationFileElement)
 {
     return(configurationFileElement.GetAttributeValue <string>(ConfigurationFileAttributeNames.Name));
 }
예제 #4
0
 /// <summary>
 /// </summary>
 /// <param name="configurationFileElement"></param>
 /// <exception cref="ConfigurationParseException">
 ///     Throws this exception if the attribute value cannot be conveted to a
 ///     boolean value.
 /// </exception>
 internal static bool GetEnabledAttributeValue(this IConfigurationFileElement configurationFileElement)
 {
     return(configurationFileElement.GetAttributeValue <bool>(ConfigurationFileAttributeNames.Enabled));
 }
예제 #5
0
        /// <summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="configurationFileElement"></param>
        /// <param name="attributeName"></param>
        /// <returns></returns>
        /// <exception cref="ConfigurationParseException">
        ///     Throws this exception if the attribute value cannot be converted to type
        ///     of 'T'.
        /// </exception>
        internal static T GetAttributeValue <T>(this IConfigurationFileElement configurationFileElement, string attributeName)
        {
            var typeOfConvertedValue = typeof(T);

            var attributeValue = configurationFileElement.GetAttributeValue(attributeName);

            if (typeOfConvertedValue == typeof(string))
            {
                return((T)(object)attributeValue);
            }

            try
            {
                if (typeOfConvertedValue == typeof(double) || typeOfConvertedValue == typeof(float))
                {
                    return((T)(object)double.Parse(attributeValue));
                }

                if (typeOfConvertedValue == typeof(long))
                {
                    return((T)(object)long.Parse(attributeValue));
                }

                if (typeOfConvertedValue == typeof(int))
                {
                    return((T)(object)int.Parse(attributeValue));
                }

                if (typeOfConvertedValue == typeof(short))
                {
                    return((T)(object)short.Parse(attributeValue));
                }

                if (typeOfConvertedValue == typeof(byte))
                {
                    return((T)(object)short.Parse(attributeValue));
                }

                if (typeOfConvertedValue == typeof(bool))
                {
                    if (attributeValue.Equals("1"))
                    {
                        return((T)(object)true);
                    }

                    if (attributeValue.Equals("0"))
                    {
                        return((T)(object)false);
                    }

                    return((T)(object)bool.Parse(attributeValue));
                }

                if (typeOfConvertedValue == typeof(DateTime))
                {
                    return((T)(object)DateTime.Parse(attributeValue));
                }

                LogHelper.Context.Log.WarnFormat("Unhandled type '{0}' in '{1}.{2}().'", typeOfConvertedValue, typeof(Helpers).FullName, nameof(GetAttributeValue));
            }
            catch
            {
                // We will throw exception next.
            }

            // If we didn't return anything, throw.
            throw new ConfigurationParseException(configurationFileElement,
                                                  $"Attribute '{attributeName}' should have valid non-empty value of type '{typeof(T).FullName}'.");
        }
예제 #6
0
        private ITypeInfo GetTypeInfo2([NotNull] IConfigurationFileElement requestingConfigurationFileElement,
                                       [NotNull] ITypeData typeData,
                                       [NotNull] string assemblyAttributeName,
                                       [NotNull][ItemNotNull] IReadOnlyList <ITypeInfo> genericTypeParametersList)
        {
            IAssembly assembly = null;

            if (assemblyAttributeName != null && requestingConfigurationFileElement.HasAttribute(assemblyAttributeName))
            {
                assembly = Helpers.GetAssemblySettingByAssemblyAlias(requestingConfigurationFileElement, requestingConfigurationFileElement.GetAttributeValue <string>(assemblyAttributeName));
            }

            string typeFullNameWithGenericParameters;

            {
                var typeFullNameWithGenericParametersStrBldr = new StringBuilder();
                if (genericTypeParametersList.Count > 0)
                {
                    typeFullNameWithGenericParametersStrBldr.Append($"{typeData.TypeFullNameWithoutGenericParameters}<{string.Join(",", genericTypeParametersList.Select(x => x.TypeCSharpFullName))}>");
                }
                else
                {
                    typeFullNameWithGenericParametersStrBldr.Append(typeData.TypeFullNameWithoutGenericParameters);
                }

                if (typeData.IsArray)
                {
                    typeFullNameWithGenericParametersStrBldr.Append("[]");
                }

                typeFullNameWithGenericParameters = typeFullNameWithGenericParametersStrBldr.ToString();
            }

            System.Reflection.Assembly assemblyToLoadTypeFrom = null;

            if (assembly != null)
            {
                assemblyToLoadTypeFrom = LoadAssembly(assembly);
            }

            var    lastIndexOfDotInType   = typeData.TypeFullNameWithoutGenericParameters.LastIndexOf('.');
            string typePotentialNamespace = lastIndexOfDotInType > 0 && lastIndexOfDotInType < typeData.TypeFullNameWithoutGenericParameters.Length - 1 ?
                                            typeData.TypeFullNameWithoutGenericParameters.Substring(0, lastIndexOfDotInType) : null;

            IEnumerable <IoC.Configuration.IAssembly> assembliesToSearch;

            if (assembly != null)
            {
                assembliesToSearch = new IoC.Configuration.IAssembly[] { assembly };
            }
            else
            {
                if (typePotentialNamespace != null)
                {
                    var assembliesThatArePartOfNamespace        = new List <IoC.Configuration.IAssembly>();
                    var assembliesThatContainNamespacePart      = new List <IoC.Configuration.IAssembly>();
                    var assembliesThatDoNotContainNamespacePart = new List <IoC.Configuration.IAssembly>();

                    foreach (var currentAssembly in requestingConfigurationFileElement.Configuration.Assemblies.AllAssembliesIncludingAssembliesNotInConfiguration)
                    {
                        if (typePotentialNamespace.StartsWith(currentAssembly.Name))
                        {
                            assembliesThatArePartOfNamespace.Add(currentAssembly);
                        }
                        else
                        {
                            var indexOfDot = currentAssembly.Name.IndexOf('.');

                            if (indexOfDot >= 0 && typePotentialNamespace.StartsWith(
                                    string.Concat(currentAssembly.Name.Substring(0, indexOfDot), ".")))
                            {
                                assembliesThatContainNamespacePart.Add(currentAssembly);
                            }
                            else
                            {
                                assembliesThatDoNotContainNamespacePart.Add(currentAssembly);
                            }
                        }
                    }

                    var assembliesToSearchList = new List <IoC.Configuration.IAssembly>(
                        assembliesThatArePartOfNamespace.Count + assembliesThatContainNamespacePart.Count + assembliesThatDoNotContainNamespacePart.Count);

                    assembliesToSearchList.AddRange(assembliesThatArePartOfNamespace);
                    assembliesToSearchList.AddRange(assembliesThatContainNamespacePart);
                    assembliesToSearchList.AddRange(assembliesThatDoNotContainNamespacePart);
                    assembliesToSearch = assembliesToSearchList;
                }
                else
                {
                    assembliesToSearch = requestingConfigurationFileElement.Configuration.Assemblies.AllAssembliesIncludingAssembliesNotInConfiguration;
                }
            }

            if (!_typeFullNameToTypeInfo.TryGetValue(typeFullNameWithGenericParameters, out var typeInfo))
            {
                ITypeInfo tryFindTypeInAssemblies(bool tryLocalType)
                {
                    if (tryLocalType && typePotentialNamespace == null)
                    {
                        return(null);
                    }

                    var internalTypeNameStrBldr = new StringBuilder();

                    if (tryLocalType)
                    {
                        internalTypeNameStrBldr.Append($"{typePotentialNamespace}+{typeData.TypeFullNameWithoutGenericParameters.Substring(lastIndexOfDotInType + 1)}");
                    }
                    else
                    {
                        internalTypeNameStrBldr.Append(typeData.TypeFullNameWithoutGenericParameters);
                    }

                    if (genericTypeParametersList.Count > 0)
                    {
                        internalTypeNameStrBldr.Append($"`{genericTypeParametersList.Count}");
                    }

                    var internalTypeName = internalTypeNameStrBldr.ToString();

                    foreach (var currAssembly in assembliesToSearch)
                    {
                        System.Reflection.Assembly currAssemblyToLoadTypeFrom;

                        if (currAssembly == assembly)
                        {
                            currAssemblyToLoadTypeFrom = assemblyToLoadTypeFrom;
                        }
                        else
                        {
                            if (currAssembly is IAssembly assemblyElement)
                            {
                                currAssemblyToLoadTypeFrom = LoadAssembly(assemblyElement);
                            }
                            else
                            {
                                currAssemblyToLoadTypeFrom = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x =>
                                                                                                                    currAssembly.Name.Equals(x.GetName().Name, StringComparison.OrdinalIgnoreCase));

                                if (currAssemblyToLoadTypeFrom == null)
                                {
                                    throw new ConfigurationParseException(requestingConfigurationFileElement,
                                                                          $"Assembly '{currAssembly.Name}' is not loaded. There should be an error in code, since this scenario should never happen.");
                                }
                            }
                        }

                        var loadedType = currAssemblyToLoadTypeFrom.GetType(internalTypeName, false, false);

                        if (loadedType != null)
                        {
                            if (genericTypeParametersList.Count > 0)
                            {
                                internalTypeNameStrBldr.Append('[');
                                for (var i = 0; i < genericTypeParametersList.Count; ++i)
                                {
                                    var genericTypeParameterType = genericTypeParametersList[i];

                                    if (i > 0)
                                    {
                                        internalTypeNameStrBldr.Append(", ");
                                    }

                                    internalTypeNameStrBldr.AppendFormat($"[{genericTypeParameterType.TypeInternalFullNameWithAssembly}]");
                                }

                                internalTypeNameStrBldr.Append(']');
                                internalTypeName = internalTypeNameStrBldr.ToString();

                                loadedType = currAssemblyToLoadTypeFrom.GetType(internalTypeName, false, false);
                            }

                            if (loadedType != null)
                            {
                                if (typeData.IsArray)
                                {
                                    return(TypeInfo.CreateArrayTypeInfo(loadedType, currAssembly, genericTypeParametersList));
                                }
                                return(TypeInfo.CreateNonArrayTypeInfo(loadedType, currAssembly, genericTypeParametersList));
                            }
                        }
                    }

                    return(null);
                }

                typeInfo = tryFindTypeInAssemblies(false);

                if (typeInfo == null)
                {
                    typeInfo = tryFindTypeInAssemblies(true);
                }

                if (typeInfo == null)
                {
                    var searchedAssembliesDetails = new StringBuilder();

                    searchedAssembliesDetails.Append($"Type '{typeFullNameWithGenericParameters}' was not found");

                    if (assembly != null)
                    {
                        searchedAssembliesDetails.AppendLine($" in assembly '{assembly.Name}' with alias '{assembly.Alias}' at the path '{assembly.AbsolutePath}'.");
                        searchedAssembliesDetails.AppendLine($"To fix the problem, either specify a correct assembly, or remove the attribute '{assemblyAttributeName}' from element '{requestingConfigurationFileElement.ElementName}' to look for the type in all assemblies specified in element 'iocConfiguration/{ConfigurationFileElementNames.Assemblies}'.");
                    }
                    else
                    {
                        searchedAssembliesDetails.AppendLine(".");
                        searchedAssembliesDetails.AppendLine($"Make sure that the assembly where the type is defined is included in element iocConfiguration/{ConfigurationFileElementNames.Assemblies}'.");
                        searchedAssembliesDetails.Append(GetSearchedAssembliesText(assembliesToSearch));
                    }

                    throw new ConfigurationParseException(requestingConfigurationFileElement, searchedAssembliesDetails.ToString());
                }

                _typeFullNameToTypeInfo[typeFullNameWithGenericParameters] = typeInfo;

                LogHelper.Context.Log.Info($"Loaded type '{typeInfo.TypeCSharpFullName}' from assembly '{typeInfo.Assembly.Name}' at '{typeInfo.Type.Assembly.Location}'.");
            }

            if (assembly != null && !typeInfo.Assembly.Name.Equals(assembly.Name))
            {
                var errorMessage = new StringBuilder();
                errorMessage.AppendLine($"Type '{typeInfo.TypeCSharpFullName}' was found in assembly '{typeInfo.Assembly.Name}'.");

                errorMessage.AppendLine($"The type is expected to be in assembly '{assembly.Name}'.");
                errorMessage.AppendLine($"Either remove the attribute '{assemblyAttributeName}' from element, or make sure that the type is defined only in assembly '{assembly.Name}' at '{assembly.AbsolutePath}'.");

                throw new ConfigurationParseException(requestingConfigurationFileElement, errorMessage.ToString());
            }

            return(typeInfo);
        }