// 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;
}
}
}