// 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 { /// /// Provides a for interface types which implement /// . /// public class EnumerableWrapperProvider : IWrapperProvider { private readonly IWrapperProvider _wrapperProvider; private readonly ConstructorInfo _wrappingTypeConstructor; /// /// Initializes an instance of . /// /// Type of the original /// that is being wrapped. /// The for the element type. /// Can be null. public EnumerableWrapperProvider( Type sourceEnumerableOfT, IWrapperProvider elementWrapperProvider) { if (sourceEnumerableOfT == null) { throw new ArgumentNullException(nameof(sourceEnumerableOfT)); } var enumerableOfT = ClosedGenericMatcher.ExtractGenericInterface( sourceEnumerableOfT, typeof(IEnumerable<>)); if (!sourceEnumerableOfT.GetTypeInfo().IsInterface || enumerableOfT == null) { throw new ArgumentException( Resources.FormatEnumerableWrapperProvider_InvalidSourceEnumerableOfT(typeof(IEnumerable<>).Name), nameof(sourceEnumerableOfT)); } _wrapperProvider = elementWrapperProvider; var declaredElementType = enumerableOfT.GenericTypeArguments[0]; var wrappedElementType = elementWrapperProvider?.WrappingType ?? declaredElementType; WrappingType = typeof(DelegatingEnumerable<,>).MakeGenericType(wrappedElementType, declaredElementType); _wrappingTypeConstructor = WrappingType.GetConstructor(new[] { sourceEnumerableOfT, typeof(IWrapperProvider) }); } /// public Type WrappingType { get; } /// public object Wrap(object original) { if (original == null) { return null; } return _wrappingTypeConstructor.Invoke(new[] { original, _wrapperProvider }); } } }