Created
July 16, 2017 18:09
-
-
Save jbe2277/7ebb750bad8651360cdd1258433fdb21 to your computer and use it in GitHub Desktop.
Reflection Context that maps MEF2 (NuGet 'System.Composition') attributes to MEF1 (.NET 4.x 'System.ComponentModel.Composition') attributes. This class enables an application hosting MEF1 to use libraries which export their parts via MEF2 attributes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.Composition; | |
using System.Linq; | |
using System.Reflection; | |
using System.Reflection.Context; | |
namespace WafApplication | |
{ | |
// .NET 4.x Reference: | |
// - System.ComponentModel.Composition | |
// - System.Reflection.Context | |
// | |
// NuGet: | |
// - System.Composition | |
/// <summary> | |
/// Reflection Context that maps MEF2 (NuGet 'System.Composition') attributes to MEF1 (.NET 4.x 'System.ComponentModel.Composition') attributes. | |
/// This class enables an application hosting MEF1 to use libraries which export their parts via MEF2 attributes. | |
/// </summary> | |
/// <remarks> | |
/// Usage: Pass an instance of this class to a catalog (e.g. AssemblyCatalog). | |
/// Compatibility: Not all MEF2 attributes can be mapped to MEF1 attributes because MEF1 does not support all MEF2 features. This class throws a | |
/// NotSupportedException when an attribute is found which cannot be mapped. | |
/// Inherited MEF2 attributes are mapped to compatible MEF1 base class attributes. | |
/// Performance: Using this reflection context comes with some performance penalties during catalog initialization. | |
/// </remarks> | |
public sealed class Mef2ToMef1ReflectionContext : CustomReflectionContext | |
{ | |
/// <inheritdoc /> | |
protected override IEnumerable<object> GetCustomAttributes(MemberInfo member, IEnumerable<object> declaredAttributes) | |
{ | |
if (declaredAttributes?.Any() == true) return declaredAttributes; // declaredAttributes are set when MEF1 finds attributes | |
return GetCustomAttributesCore(); | |
IEnumerable<object> GetCustomAttributesCore() | |
{ | |
bool exportFound = false; | |
bool sharedFound = false; | |
foreach (var attribute in member.GetCustomAttributes(true)) | |
{ | |
switch (attribute) | |
{ | |
case System.Composition.ExportAttribute ea: | |
yield return new ExportAttribute(ea.ContractName, ea.ContractType); | |
exportFound = true; | |
break; | |
case System.Composition.ExportMetadataAttribute ema: | |
yield return new ExportMetadataAttribute(ema.Name, ema.Value); | |
break; | |
case System.Composition.ImportAttribute ia: | |
yield return new ImportAttribute(ia.ContractName) { AllowDefault = ia.AllowDefault }; | |
break; | |
case System.Composition.ImportingConstructorAttribute ica: | |
yield return new ImportingConstructorAttribute(); | |
break; | |
case System.Composition.ImportManyAttribute ima: | |
yield return new ImportManyAttribute(ima.ContractName); | |
break; | |
case System.Composition.ImportMetadataConstraintAttribute imca: | |
throw new NotSupportedException(nameof(System.Composition.ImportMetadataConstraintAttribute)); | |
case System.Composition.MetadataAttributeAttribute maa: | |
yield return new MetadataAttributeAttribute(); | |
break; | |
case System.Composition.OnImportsSatisfiedAttribute oisa: | |
throw new NotSupportedException(nameof(System.Composition.OnImportsSatisfiedAttribute)); | |
case System.Composition.PartNotDiscoverableAttribute pnda: | |
yield return new PartNotDiscoverableAttribute(); | |
break; | |
case System.Composition.SharedAttribute sa: | |
if (!string.IsNullOrEmpty(sa.SharingBoundary)) throw new NotSupportedException(nameof(System.Composition.SharedAttribute) + "." + nameof(sa.SharingBoundary)); | |
yield return new PartCreationPolicyAttribute(CreationPolicy.Shared); | |
sharedFound = true; | |
break; | |
case System.Composition.SharingBoundaryAttribute sba: | |
throw new NotSupportedException(nameof(System.Composition.SharingBoundaryAttribute)); | |
case System.Composition.PartMetadataAttribute pma: // Use last as Shared inherit from it | |
yield return new PartMetadataAttribute(pma.Name, pma.Value); | |
break; | |
default: | |
yield return attribute; | |
break; | |
} | |
} | |
if (exportFound && !sharedFound) | |
{ | |
yield return new PartCreationPolicyAttribute(CreationPolicy.NonShared); | |
} | |
} | |
} | |
/// <inheritdoc /> | |
protected override IEnumerable<object> GetCustomAttributes(ParameterInfo parameter, IEnumerable<object> declaredAttributes) | |
{ | |
return declaredAttributes?.Any() == true ? declaredAttributes : parameter.GetCustomAttributes(true); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment