// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Reflection; using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Mvc.Formatters.Xml { /// /// Creates an for interface types implementing the /// type. /// public class EnumerableWrapperProviderFactory : IWrapperProviderFactory { private readonly IEnumerable _wrapperProviderFactories; /// /// Initializes an with a list /// . /// /// List of . public EnumerableWrapperProviderFactory(IEnumerable wrapperProviderFactories) { if (wrapperProviderFactories == null) { throw new ArgumentNullException(nameof(wrapperProviderFactories)); } _wrapperProviderFactories = wrapperProviderFactories; } /// /// Gets an for the provided context. /// /// The . /// An instance of if the declared type is /// an interface and implements . public IWrapperProvider GetProvider(WrapperProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.IsSerialization) { // Example: IEnumerable var declaredType = context.DeclaredType; var declaredTypeInfo = declaredType.GetTypeInfo(); // We only wrap interfaces types(ex: IEnumerable, IQueryable, IList etc.) and not // concrete types like List, Collection which implement IEnumerable. if (declaredType != null && declaredTypeInfo.IsInterface && declaredTypeInfo.IsGenericType) { var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface( declaredType, typeof(IEnumerable<>)); if (enumerableOfT != null) { var elementType = enumerableOfT.GenericTypeArguments[0]; var wrapperProviderContext = new WrapperProviderContext(elementType, context.IsSerialization); var elementWrapperProvider = _wrapperProviderFactories.GetWrapperProvider(wrapperProviderContext); return new EnumerableWrapperProvider(enumerableOfT, elementWrapperProvider); } } } return null; } } }