|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Composition.Hosting.Core;
using System.Composition.Hosting.Util;
using System.Linq;
using System.Reflection;
namespace System.Composition.Hosting.Providers.ImportMany
{
internal sealed class ImportManyExportDescriptorProvider : ExportDescriptorProvider
{
private static readonly MethodInfo s_getImportManyDefinitionMethod = typeof(ImportManyExportDescriptorProvider).GetTypeInfo().GetDeclaredMethod("GetImportManyDescriptor");
private static readonly Type[] s_supportedContractTypes = new[] { typeof(IList<>), typeof(ICollection<>), typeof(IEnumerable<>) };
public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor definitionAccessor)
{
if (!(contract.ContractType.IsArray ||
contract.ContractType.IsConstructedGenericType && s_supportedContractTypes.Contains(contract.ContractType.GetGenericTypeDefinition())))
return NoExportDescriptors;
bool isImportMany;
CompositionContract unwrapped;
if (!contract.TryUnwrapMetadataConstraint(Constants.ImportManyImportMetadataConstraintName, out isImportMany, out unwrapped))
return NoExportDescriptors;
var elementType = contract.ContractType.IsArray ?
contract.ContractType.GetElementType() :
contract.ContractType.GenericTypeArguments[0];
var elementContract = unwrapped.ChangeType(elementType);
var gimd = s_getImportManyDefinitionMethod.MakeGenericMethod(elementType);
var gimdm = gimd.CreateStaticDelegate<Func<CompositionContract, CompositionContract, DependencyAccessor, object>>();
return new[] { (ExportDescriptorPromise)gimdm(contract, elementContract, definitionAccessor) };
}
private static ExportDescriptorPromise GetImportManyDescriptor<TElement>(CompositionContract importManyContract, CompositionContract elementContract, DependencyAccessor definitionAccessor)
{
return new ExportDescriptorPromise(
importManyContract,
typeof(TElement[]).Name,
false,
() => definitionAccessor.ResolveDependencies("item", elementContract, true),
d =>
{
var dependentDescriptors = d
.Select(el => el.Target.GetDescriptor())
.ToArray();
return ExportDescriptor.Create((c, o) => dependentDescriptors.Select(e => (TElement)e.Activator(c, o)).ToArray(), NoMetadata);
});
}
}
}
|