示例#1
0
        /// <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);
                }
            }
        }
示例#2
0
        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);
        }
示例#3
0
        /// <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>());
        }
示例#4
0
        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();
                }
            }
        }
示例#5
0
        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());
        }
示例#6
0
        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());
        }
示例#7
0
        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);
        }