Пример #1
0
        /// <summary>
        ///		Gets all formatter that are invokable with on the given type and with the arguments.
        /// </summary>
        public virtual IEnumerable <MorestachioFormatterModel> PrepareGetMatchingFormatterOn(
            Type typeToFormat,
            FormatterArgumentType[] arguments,
            ParserOptions parserOptions,
            string name)
        {
            Log(parserOptions, () => $"Lookup formatter for type {typeToFormat} with name {name}",
                () => arguments.ToDictionary(e => e.Name, e => (object)e));

            if (!Formatters.TryGetValue(name ?? "{NULL}", out var formatters))
            {
                Log(parserOptions, () => $"There are no formatters for the name {name}");
                return(Enumerable.Empty <MorestachioFormatterModel>());
            }

            var filteredSourceList = new List <KeyValuePair <MorestachioFormatterModel, ulong> >();

            foreach (var formatTemplateElement in formatters)
            {
                Log(parserOptions, () => $"Test formatter input type: '{formatTemplateElement.InputType}' on formatter named '{formatTemplateElement.Function.Name}'");

                if (formatTemplateElement.InputType != typeToFormat &&
                    !formatTemplateElement.InputType.GetTypeInfo().IsAssignableFrom(typeToFormat))
                {
                    if (ValueConverter.All(e => !e.CanConvert(typeToFormat, formatTemplateElement.InputType)))
                    {
                        if (formatTemplateElement.MetaData.SourceObject != null &&
                            formatTemplateElement.MetaData.SourceObject.FormatterValueConverterAttribute
                            .Select(e => e.CreateInstance())
                            .All(e => !e.CanConvert(typeToFormat, formatTemplateElement.InputType)))
                        {
                            if (!CheckGenericTypeForMatch(typeToFormat, formatTemplateElement))
                            {
                                var foundInterface = false;
                                //TODO cleanup this mess or rewrite the generic interface matching!
                                //foreach (var @interface in typeToFormat.GetInterfaces())
                                //{
                                //	if (CheckGenericTypeForMatch(@interface, formatTemplateElement))
                                //	{
                                //		foundInterface = true;
                                //	}
                                //}

                                if (!foundInterface)
                                {
                                    Log(parserOptions, () =>
                                        $"Exclude because formatter accepts '{formatTemplateElement.InputType}' is not assignable from '{typeToFormat}'");
                                    continue;
                                }
                            }
                        }
                    }
                }

                //count rest arguments
                //var mandatoryArguments = formatTemplateElement.MetaData
                //	.Where(e => !e.IsRestObject && !e.IsOptional && !e.IsSourceObject && !e.IsInjected).ToArray();
                if (formatTemplateElement.MetaData.MandetoryArguments.Count > arguments.Length)
                //if there are less arguments excluding rest then parameters
                {
                    Log(parserOptions, () =>
                        "Exclude because formatter has " +
                        $"'{formatTemplateElement.MetaData.MandetoryArguments.Count}' " +
                        "parameter and " +
                        $"'{formatTemplateElement.MetaData.Count(e => e.IsRestObject)}' " +
                        "rest parameter but needs less or equals" +
                        $"'{arguments.Length}'.");
                    continue;
                }

                ulong score = 1L;
                if (formatTemplateElement.Function.ReturnParameter == null ||
                    formatTemplateElement.Function.ReturnParameter?.ParameterType == typeof(void))
                {
                    score++;
                }

                score += (ulong)(arguments.Length - formatTemplateElement.MetaData.MandetoryArguments.Count);
                Log(parserOptions, () =>
                    $"Take filter: '{formatTemplateElement.InputType} : {formatTemplateElement.Function}' Score {score}");
                filteredSourceList.Add(
                    new KeyValuePair <MorestachioFormatterModel, ulong>(formatTemplateElement, score));
            }

            if (filteredSourceList.Count > 0)
            {
                var formatter = new List <MorestachioFormatterModel>();
                foreach (var formatTemplateElement in filteredSourceList.OrderBy(e => e.Value))
                {
                    formatter.Add(formatTemplateElement.Key);
                }

                return(formatter);
            }
            Log(parserOptions, () => "No formatter matches");
            return(Enumerable.Empty <MorestachioFormatterModel>());
        }
Пример #2
0
        /// <summary>
        ///     Gets the matching formatter.
        /// </summary>
        public virtual IEnumerable <MorestachioFormatterModel> GetMatchingFormatter(
            [CanBeNull] object sourceValue,
            [NotNull] Type typeToFormat,
            [NotNull] KeyValuePair <string, object>[] arguments,
            [CanBeNull] string name)
        {
            Log(() =>
            {
                var aggregate = arguments.Any() ? arguments.Select(e => $"[{e.Key}]:\"{e.Value}\"").Aggregate((e, f) => e + " & " + f) : "";
                return
                ($"Test Filter for '{typeToFormat}' with arguments '{aggregate}'");
            });

            var filteredSourceList = new List <KeyValuePair <MorestachioFormatterModel, ulong> >();

            foreach (MorestachioFormatterModel formatTemplateElement in Formatters)
            {
                if (!string.Equals(formatTemplateElement.Name, name, FormatterNameCompareMode))
                {
                    continue;
                }

                Log(() => $"Test filter: '{formatTemplateElement.InputType} : {formatTemplateElement.Function.Name}'");

                if (formatTemplateElement.InputType != typeToFormat &&
                    !formatTemplateElement.InputType.GetTypeInfo().IsAssignableFrom(typeToFormat))
                {
                    if (ValueConverter.All(e => !e.CanConvert(sourceValue, formatTemplateElement.InputType)))
                    {
                        if (formatTemplateElement.MetaData.SourceValue().FormatterValueConverterAttribute.Select(e => e.CreateInstance())
                            .All(e => !e.CanConvert(sourceValue, formatTemplateElement.InputType)))
                        {
                            var typeToFormatGenerics = typeToFormat.GetTypeInfo().GetGenericArguments();

                            //explicit check for array support
                            if (typeToFormat.HasElementType)
                            {
                                var elementType = typeToFormat.GetElementType();
                                typeToFormatGenerics = typeToFormatGenerics.Concat(new[]
                                {
                                    elementType
                                }).ToArray();
                            }

                            //the type check has maybe failed because of generic parameter. Check if both the formatter and the typ have generic arguments

                            var formatterGenerics = formatTemplateElement.InputType.GetTypeInfo().GetGenericArguments();

                            if (typeToFormatGenerics.Length <= 0 || formatterGenerics.Length <= 0 ||
                                typeToFormatGenerics.Length != formatterGenerics.Length)
                            {
                                Log(() =>
                                    $"Exclude because formatter accepts '{formatTemplateElement.InputType}' is not assignable from '{typeToFormat}'");
                                continue;
                            }
                        }
                    }
                }

                //count rest arguments
                var mandatoryArguments = formatTemplateElement.MetaData
                                         .Where(e => !e.IsRestObject && !e.IsOptional && !e.IsSourceObject).ToArray();
                if (mandatoryArguments.Length > arguments.Length)
                //if there are less arguments excluding rest then parameters
                {
                    Log(() =>
                        "Exclude because formatter has " +
                        $"'{mandatoryArguments.Length}' " +
                        "parameter and " +
                        $"'{formatTemplateElement.MetaData.Count(e => e.IsRestObject)}' " +
                        "rest parameter but needs less or equals" +
                        $"'{arguments.Length}'.");
                    continue;
                }

                ulong score = 1L;
                if (formatTemplateElement.Function.ReturnParameter == null ||
                    formatTemplateElement.Function.ReturnParameter?.ParameterType == typeof(void))
                {
                    score++;
                }

                score += (ulong)(arguments.Length - mandatoryArguments.Length);
                Log(() => $"Take filter: '{formatTemplateElement.InputType} : {formatTemplateElement.Function}' Score {score}");
                filteredSourceList.Add(new KeyValuePair <MorestachioFormatterModel, ulong>(formatTemplateElement, score));
            }

            var formatter = new List <MorestachioFormatterModel>();

            foreach (var formatTemplateElement in filteredSourceList.OrderBy(e => e.Value))
            {
                formatter.Add(formatTemplateElement.Key);
            }

            return(formatter);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="typeToFormat"></param>
        /// <param name="arguments"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public virtual IEnumerable <MorestachioFormatterModel> PrepareGetMatchingFormatterOn(
            [NotNull] Type typeToFormat,
            [NotNull] FormatterArgumentType[] arguments,
            [CanBeNull] string name)
        {
            var filteredSourceList = new List <KeyValuePair <MorestachioFormatterModel, ulong> >();

            if (!Formatters.TryGetValue(name ?? "{NULL}", out var formatters))
            {
                return(Enumerable.Empty <MorestachioFormatterModel>());
            }

            foreach (var formatTemplateElement in formatters)
            {
                Log(() => $"Test filter: '{formatTemplateElement.InputType} : {formatTemplateElement.Function.Name}'");

                if (formatTemplateElement.InputType != typeToFormat &&
                    !formatTemplateElement.InputType.GetTypeInfo().IsAssignableFrom(typeToFormat))
                {
                    if (ValueConverter.All(e => !e.CanConvert(typeToFormat, formatTemplateElement.InputType)))
                    {
                        if (formatTemplateElement.MetaData.SourceObject != null &&
                            formatTemplateElement.MetaData.SourceObject.FormatterValueConverterAttribute
                            .Select(e => e.CreateInstance())
                            .All(e => !e.CanConvert(typeToFormat, formatTemplateElement.InputType)))
                        {
                            var typeToFormatGenerics = typeToFormat.GetTypeInfo().GetGenericArguments();

                            //explicit check for array support
                            if (typeToFormat.HasElementType)
                            {
                                var elementType = typeToFormat.GetElementType();
                                typeToFormatGenerics = typeToFormatGenerics.Concat(new[]
                                {
                                    elementType
                                }).ToArray();
                            }

                            //the type check has maybe failed because of generic parameter. Check if both the formatter and the typ have generic arguments

                            var formatterGenerics = formatTemplateElement.InputType.GetTypeInfo().GetGenericArguments();

                            if (typeToFormatGenerics.Length <= 0 || formatterGenerics.Length <= 0 ||
                                typeToFormatGenerics.Length != formatterGenerics.Length)
                            {
                                Log(() =>
                                    $"Exclude because formatter accepts '{formatTemplateElement.InputType}' is not assignable from '{typeToFormat}'");
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                }

                //count rest arguments
                //var mandatoryArguments = formatTemplateElement.MetaData
                //	.Where(e => !e.IsRestObject && !e.IsOptional && !e.IsSourceObject && !e.IsInjected).ToArray();
                if (formatTemplateElement.MetaData.MandetoryArguments.Count > arguments.Length)
                //if there are less arguments excluding rest then parameters
                {
                    Log(() =>
                        "Exclude because formatter has " +
                        $"'{formatTemplateElement.MetaData.MandetoryArguments.Count}' " +
                        "parameter and " +
                        $"'{formatTemplateElement.MetaData.Count(e => e.IsRestObject)}' " +
                        "rest parameter but needs less or equals" +
                        $"'{arguments.Length}'.");
                    continue;
                }

                ulong score = 1L;
                if (formatTemplateElement.Function.ReturnParameter == null ||
                    formatTemplateElement.Function.ReturnParameter?.ParameterType == typeof(void))
                {
                    score++;
                }

                score += (ulong)(arguments.Length - formatTemplateElement.MetaData.MandetoryArguments.Count);
                Log(() =>
                    $"Take filter: '{formatTemplateElement.InputType} : {formatTemplateElement.Function}' Score {score}");
                filteredSourceList.Add(
                    new KeyValuePair <MorestachioFormatterModel, ulong>(formatTemplateElement, score));
            }

            if (filteredSourceList.Count > 0)
            {
                var formatter = new List <MorestachioFormatterModel>();
                foreach (var formatTemplateElement in filteredSourceList.OrderBy(e => e.Value))
                {
                    formatter.Add(formatTemplateElement.Key);
                }

                return(formatter);
            }

            return(Enumerable.Empty <MorestachioFormatterModel>());
        }