/// <summary> /// Register a MEF part definition. /// </summary> /// <param name="builder">The container builder.</param> /// <param name="partDefinition">The part definition to register.</param> /// <param name="exposedServicesMapper">A mapping function to transform ExportDefinitions into Services.</param> public static void RegisterComposablePartDefinition(this ContainerBuilder builder, ComposablePartDefinition partDefinition, Func <ExportDefinition, IEnumerable <Service> > exposedServicesMapper) { if (builder == null) { throw new ArgumentNullException("builder"); } if (partDefinition == null) { throw new ArgumentNullException("partDefinition"); } if (exposedServicesMapper == null) { throw new ArgumentNullException("exposedServicesMapper"); } var partId = new UniqueService(); var partRegistration = builder.Register(c => partDefinition.CreatePart()) .OnActivating(e => SetPrerequisiteImports(e.Context, e.Instance)) .OnActivated(e => SetNonPrerequisiteImports(e.Context, e.Instance)) .As(partId); if (IsSharedInstance(partDefinition)) { partRegistration.SingleInstance(); } foreach (var iterExportDef in partDefinition.ExportDefinitions) { var exportDef = iterExportDef; var contractService = new ContractBasedService(exportDef.ContractName, GetTypeIdentity(exportDef)); var exportId = new UniqueService(); builder.Register(c => { var p = ((ComposablePart)c.ResolveService(partId)); return(new Export(exportDef, () => p.GetExportedValue(exportDef))); }) .As(exportId, contractService) .ExternallyOwned() .WithMetadata(exportDef.Metadata); var additionalServices = exposedServicesMapper(exportDef).ToArray(); if (additionalServices.Length > 0) { builder.Register(c => ((Export)c.ResolveService(exportId)).Value) .As(additionalServices) .ExternallyOwned() .WithMetadata(exportDef.Metadata); } } }
private static IEnumerable <Export> ResolveExports(this IComponentContext context, ContractBasedImportDefinition cbid) { var contractService = new ContractBasedService(cbid.ContractName, cbid.RequiredTypeIdentity); var componentsForContract = context.ComponentsForContract(cbid, contractService); var exportsForContract = componentsForContract .Select(cpt => context.ResolveComponent(new ResolveRequest(contractService, cpt, Enumerable.Empty <Parameter>()))) .Cast <Export>() .ToList(); return(exportsForContract); }
/// <summary> /// Locate all of the MEF exports registered as supplying contract type T. /// </summary> /// <param name="contractName">The contract name.</param> /// <param name="context">The context to resolve exports from.</param> /// <returns>A list of exports.</returns> public static IEnumerable <Export> ResolveExports <T>(this IComponentContext context, string contractName) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var service = new ContractBasedService(contractName, AttributedModelServices.GetTypeIdentity(typeof(T))); return(context.ComponentRegistry .RegistrationsFor(service) .Select(cpt => context.ResolveComponent(new ResolveRequest(service, cpt, Enumerable.Empty <Parameter>()))) .Cast <Export>()); }
private static void ProcessExportDefinition(ContainerBuilder builder, Func <ExportDefinition, IEnumerable <Service> > exposedServicesMapper, UniqueService partId, ExportDefinition iterExportDef) { var exportDef = iterExportDef; var contractService = new ContractBasedService(exportDef.ContractName, GetTypeIdentity(exportDef)); var exportIsShared = IsSharedInstance(exportDef); var exportId = new UniqueService(); var exportReg = builder.Register(c => { var p = (ComposablePart)c.ResolveService(partId); return(new Export(exportDef, () => p.GetExportedValue(exportDef))); }) .As(exportId, contractService) .ExternallyOwned() .WithMetadata(exportDef.Metadata); // Issue #348: When a constructor takes in a duplicate dependency like: // public ImportsDuplicateMefClass(ImportsMefDependency first, ImportsMefDependency second) // and each of those dependencies also take in the same thing: // public ImportsMefDependency(IDependency dependency) // Then when the export/import process gets run, if the export doesn't have // the same lifetime scope sharing (per-instance vs. singleton) you // have trouble because the OnActivating from above in the original part // registration doesn't run, the chained-in prerequisite imports never get // populated, and everything fails. Setting the export registrations to be // the same lifetime scope as the part they correspond to fixes the issue. if (exportIsShared) { exportReg.SingleInstance(); } var additionalServices = exposedServicesMapper(exportDef).ToArray(); if (additionalServices.Length > 0) { var addlReg = builder.Register(c => ((Export)c.ResolveService(exportId)).Value) .As(additionalServices) .ExternallyOwned() .WithMetadata(exportDef.Metadata); if (exportIsShared) { addlReg.SingleInstance(); } } }
private static void AttachExport(IComponentRegistryBuilder registry, IComponentRegistration registration, ExportConfigurationBuilder exportConfiguration) { var contractService = new ContractBasedService(exportConfiguration.ContractName, exportConfiguration.ExportTypeIdentity); var rb = RegistrationBuilder.ForDelegate((c, p) => { var ctx = c.Resolve <IComponentContext>(); return(new Export( new ExportDefinition(exportConfiguration.ContractName, exportConfiguration.Metadata), () => ctx.ResolveComponent(new ResolveRequest(contractService, registration, Array.Empty <Parameter>())))); }) .As(contractService) .ExternallyOwned() .WithMetadata((IEnumerable <KeyValuePair <string, object> >)exportConfiguration.Metadata); registry.Register(rb.CreateRegistration()); }
static void AttachExport(IComponentRegistry registry, IComponentRegistration registration, ExportConfigurationBuilder exportConfiguration) { var contractService = new ContractBasedService(exportConfiguration.ContractName, exportConfiguration.ExportTypeIdentity); var rb = RegistrationBuilder.ForDelegate((c, p) => { var ctx = c.Resolve <IComponentContext>(); return(new Export( new ExportDefinition(exportConfiguration.ContractName, exportConfiguration.Metadata), () => ctx.ResolveComponent(registration, new Parameter[0]))); }) .As(contractService) .ExternallyOwned() .WithMetadata(exportConfiguration.Metadata); registry.Register(rb.CreateRegistration()); }
static IEnumerable <IComponentRegistration> ComponentsForContract(this IComponentContext context, ContractBasedImportDefinition cbid) { var contractService = new ContractBasedService(cbid.ContractName, cbid.RequiredTypeIdentity); var componentsForContract = context .ComponentRegistry .RegistrationsFor(contractService) .Where(cpt => !cbid.RequiredMetadata .Except(cpt.Metadata.Select(m => new KeyValuePair <string, Type>(m.Key, m.Value.GetType()))) .Any()) .ToList(); if (cbid.Cardinality == ImportCardinality.ExactlyOne && componentsForContract.Count == 0) { throw new ComponentNotRegisteredException(contractService); } return(componentsForContract); }