예제 #1
0
        private static HtmlFormatter <T> CreateForSequence(bool includeInternals)
        {
            Type valueType = null;
            Func <T, IEnumerable> getKeys   = null;
            Func <T, IEnumerable> getValues = instance => (IEnumerable)instance;

            var dictionaryGenericType = typeof(T).GetInterfaces()
                                        .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary <,>));
            var dictionaryObjectType = typeof(T).GetInterfaces()
                                       .FirstOrDefault(i => i == typeof(IDictionary));
            var enumerableGenericType = typeof(T).GetInterfaces()
                                        .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable <>));

            if (dictionaryGenericType != null || dictionaryObjectType != null)
            {
                var keysProperty = typeof(T).GetProperty("Keys");
                getKeys = instance => (IEnumerable)keysProperty.GetValue(instance, null);

                var valuesProperty = typeof(T).GetProperty("Values");
                getValues = instance => (IEnumerable)valuesProperty.GetValue(instance, null);

                if (dictionaryGenericType != null)
                {
                    valueType = typeof(T).GenericTypeArguments[1];
                }
            }
            else if (enumerableGenericType != null)
            {
                if (!enumerableGenericType.IsArray)
                {
                    var genericTypeArguments = typeof(T).GenericTypeArguments;

                    if (genericTypeArguments.Length == 1)
                    {
                        valueType = genericTypeArguments[0];
                    }
                }
            }

            var destructurer = valueType != null
                ? Destructurer.Create(valueType)
                : null;

            return(new HtmlFormatter <T>((instance, writer) =>
            {
                var index = 0;

                IHtmlContent indexHeader = null;

                Func <string> getIndex;

                if (getKeys != null)
                {
                    var keys = new List <string>();
                    foreach (var key in getKeys(instance))
                    {
                        keys.Add(key.ToString());
                    }

                    getIndex = () => keys[index];
                    indexHeader = th(i("key"));
                }
                else
                {
                    getIndex = () => index.ToString();
                    indexHeader = th(i("index"));
                }

                var rows = new List <IHtmlContent>();
                List <IHtmlContent> headers = null;

                foreach (var item in getValues(instance))
                {
                    var dictionary = (destructurer ?? Destructurer.Create(item.GetType())).Destructure(item);

                    if (headers == null)
                    {
                        headers = new List <IHtmlContent>();
                        headers.Add(indexHeader);
                        headers.AddRange(dictionary.Keys
                                         .Select(k => (IHtmlContent)th(k)));
                    }

                    var cells =
                        new IHtmlContent[]
                    {
                        td(getIndex().ToHtmlContent())
                    }
                    .Concat(
                        dictionary
                        .Values
                        .Select(v => (IHtmlContent)td(v)));

                    rows.Add(tr(cells));

                    index++;
                }

                var view = HtmlFormatter.Table(headers, rows);

                view.WriteTo(writer, HtmlEncoder.Default);
            }));
        }
예제 #2
0
        private static HtmlFormatter <T> CreateForSequence(bool includeInternals)
        {
            IDestructurer destructurer = null;

            if (typeof(T).IsConstructedGenericType)
            {
                var dictionaryType = typeof(T).GetInterfaces()
                                     .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary <,>));

                if (dictionaryType != null)
                {
                    var itemType = dictionaryType.GenericTypeArguments.ElementAt(1);
                    destructurer = Destructurer.Create(itemType);
                }

                if (destructurer == null)
                {
                    var ienumerableType = typeof(T).GetInterfaces()
                                          .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable <>));

                    if (ienumerableType != null)
                    {
                        var itemType = ienumerableType.GenericTypeArguments.Single();

                        destructurer = Destructurer.Create(itemType);
                    }
                }
            }

            return(new HtmlFormatter <T>((instance, writer) =>
            {
                var index = 0;

                IEnumerable sequence = instance switch {
                    IDictionary d => d.Values,
                    IEnumerable s => s,
                    _ => throw new ArgumentException($"{instance.GetType()} is not IEnumerable")
                };

                IHtmlContent indexHeader = null;

                Func <string> getIndex;

                switch (instance)
                {
                case IDictionary dict:
                    var keys = new string[dict.Keys.Count];
                    dict.Keys.CopyTo(keys, 0);
                    getIndex = () => keys[index];
                    indexHeader = th(i("key"));
                    break;

                default:
                    getIndex = () => index.ToString();
                    indexHeader = th(i("index"));
                    break;
                }

                var rows = new List <IHtmlContent>();
                List <IHtmlContent> headers = null;

                foreach (var item in sequence)
                {
                    var dictionary = (destructurer ?? Destructurer.Create(item.GetType())).Destructure(item);

                    if (headers == null)
                    {
                        headers = new List <IHtmlContent>();
                        headers.Add(indexHeader);
                        headers.AddRange(dictionary.Keys
                                         .Select(k => (IHtmlContent)th(k)));
                    }

                    var cells =
                        new IHtmlContent[]
                    {
                        td(getIndex().ToHtmlContent())
                    }
                    .Concat(
                        dictionary
                        .Values
                        .Select(v => (IHtmlContent)td(v)));

                    rows.Add(tr(cells));

                    index++;
                }

                var view = HtmlFormatter.Table(headers, rows);

                view.WriteTo(writer, HtmlEncoder.Default);
            }));
        }