|
// 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;
using System.Composition.Hosting.Core;
using System.Composition.TypedParts.ActivationFeatures;
using System.Linq;
using System.Reflection;
namespace System.Composition.TypedParts
{
internal static class ContractHelpers
{
private const string ImportManyImportMetadataConstraintName = "IsImportMany";
public static bool TryGetExplicitImportInfo(Type memberType, object[] attributes, object site, out ImportInfo importInfo)
{
if (attributes.Any(a => a is ImportAttribute || a is ImportManyAttribute))
{
importInfo = GetImportInfo(memberType, attributes, site);
return true;
}
importInfo = null;
return false;
}
public static ImportInfo GetImportInfo(Type memberType, object[] attributes, object site)
{
var importedContract = new CompositionContract(memberType);
Dictionary<string, object> importMetadata = null;
var allowDefault = false;
var explicitImportsApplied = 0;
foreach (var attr in attributes)
{
var ia = attr as ImportAttribute;
if (ia != null)
{
importedContract = new CompositionContract(memberType, ia.ContractName);
allowDefault = ia.AllowDefault;
explicitImportsApplied++;
}
else
{
var ima = attr as ImportManyAttribute;
if (ima != null)
{
importMetadata ??= new Dictionary<string, object>();
importMetadata.Add(ImportManyImportMetadataConstraintName, true);
importedContract = new CompositionContract(memberType, ima.ContractName);
explicitImportsApplied++;
}
else
{
var imca = attr as ImportMetadataConstraintAttribute;
if (imca != null)
{
importMetadata ??= new Dictionary<string, object>();
importMetadata.Add(imca.Name, imca.Value);
}
}
}
var attrType = attr.GetType();
// Note, we don't support ReflectionContext in this scenario
if (attrType.GetTypeInfo().GetCustomAttribute<MetadataAttributeAttribute>(true) != null)
{
// We don't coalesce to collections here the way export metadata does
foreach (var prop in attrType
.GetRuntimeProperties()
.Where(p => p.GetMethod.IsPublic && p.DeclaringType == attrType && p.CanRead))
{
importMetadata ??= new Dictionary<string, object>();
importMetadata.Add(prop.Name, prop.GetValue(attr, null));
}
}
}
if (explicitImportsApplied > 1)
{
string message = SR.Format(SR.ContractHelpers_TooManyImports, site);
throw new CompositionFailedException(message);
}
if (importMetadata != null)
{
importedContract = new CompositionContract(importedContract.ContractType, importedContract.ContractName, importMetadata);
}
return new ImportInfo(importedContract, allowDefault);
}
public static bool IsShared(IDictionary<string, object> partMetadata)
{
return partMetadata.ContainsKey(LifetimeFeature.SharingBoundaryPartMetadataName);
}
}
}
|