public bool IsPartDiscoverable()
        {
            // The part should not be marked with the "NonDiscoverable"
            if (_type.IsAttributeDefined <PartNotDiscoverableAttribute>())
            {
                CompositionTrace.DefinitionMarkedWithPartNotDiscoverableAttribute(_type);
                return(false);
            }

            // The part should have exports
            if (!HasExports())
            {
                CompositionTrace.DefinitionContainsNoExports(_type);
                return(false);
            }

            // If the part is generic, all exports should have the same number of generic parameters
            // (otherwise we have no way to specialize the part based on an export)
            if (!AllExportsHaveMatchingArity())
            {
                // The function has already reported all violations via tracing
                return(false);
            }

            return(true);
        }
Exemplo n.º 2
0
        private AssemblyCatalog?CreateAssemblyCatalogGuarded(string assemblyFilePath)
        {
            Exception?exception = null;

            try
            {
                return((_reflectionContext != null)
                    ? new AssemblyCatalog(assemblyFilePath, _reflectionContext, this)
                    : new AssemblyCatalog(assemblyFilePath, this));
            }
            catch (FileNotFoundException ex)
            {   // Files should always exists but don't blow up here if they don't
                exception = ex;
            }
            catch (FileLoadException ex)
            {   // File was found but could not be loaded
                exception = ex;
            }
            catch (BadImageFormatException ex)
            {   // Dlls that contain native code are not loaded, but do not invalidate the Directory
                exception = ex;
            }
            catch (ReflectionTypeLoadException ex)
            {   // Dlls that have missing Managed dependencies are not loaded, but do not invalidate the Directory
                exception = ex;
            }

            CompositionTrace.AssemblyLoadFailed(this, assemblyFilePath, exception);

            return(null);
        }
Exemplo n.º 3
0
        private static void ConfigureConstructorAttributes(ConstructorInfo constructorInfo, ref List <Tuple <object, List <Attribute> > > configuredMembers, Action <ParameterInfo, ImportBuilder> configureConstuctorImports)
        {
            if (configuredMembers == null)
            {
                configuredMembers = new List <Tuple <object, List <Attribute> > >();
            }

            // Make its attribute
            configuredMembers.Add(Tuple.Create((object)constructorInfo, s_importingConstructorList));

            //Okay we have the constructor now we can configure the ImportBuilders
            ParameterInfo[] parameterInfos = constructorInfo.GetParameters();
            foreach (ParameterInfo pi in parameterInfos)
            {
                bool isConfigured = pi.GetCustomAttributes(typeof(ImportAttribute), false).FirstOrDefault() != null || pi.GetCustomAttributes(typeof(ImportManyAttribute), false).FirstOrDefault() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_ParameterImportConventionOverridden(pi, constructorInfo);
                }
                else
                {
                    var importBuilder = new ImportBuilder();

                    // Let the developer alter them if they specified to do so
                    configureConstuctorImports?.Invoke(pi, importBuilder);

                    // Generate the attributes
                    List <Attribute> attributes = null;
                    importBuilder.BuildAttributes(pi.ParameterType, ref attributes);
                    configuredMembers.Add(Tuple.Create((object)pi, attributes));
                }
            }
        }
        private bool AllExportsHaveMatchingArity()
        {
            bool isArityMatched = true;

            if (_type.ContainsGenericParameters)
            {
                int partGenericArity = _type.GetPureGenericArity();

                // each member should have the same arity
                foreach (MemberInfo member in GetExportMembers(_type).Concat(GetInheritedExports(_type)))
                {
                    if (member.MemberType == MemberTypes.Method)
                    {
                        // open generics are unsupported on methods
                        if (((MethodInfo)member).ContainsGenericParameters)
                        {
                            isArityMatched = false;
                            CompositionTrace.DefinitionMismatchedExportArity(_type, member);
                            continue;
                        }
                    }

                    if (member.GetDefaultTypeFromMember().GetPureGenericArity() != partGenericArity)
                    {
                        isArityMatched = false;
                        CompositionTrace.DefinitionMismatchedExportArity(_type, member);
                    }
                }
            }

            return(isArityMatched);
        }
Exemplo n.º 5
0
        internal void BuildOnImportsSatisfiedNotification(Type type, ref List <Tuple <object, List <Attribute> > > configuredMembers)
        {
            //Add OnImportsSatisfiedAttribute where specified
            if (_methodImportsSatisfiedNotifications != null)
            {
                foreach (MethodInfo mi in type.GetRuntimeMethods())
                {
                    //We are only interested in void methods with no arguments
                    if (mi.ReturnParameter.ParameterType == typeof(void) &&
                        mi.GetParameters().Length == 0)
                    {
                        MethodInfo underlyingMi = mi.DeclaringType.GetRuntimeMethod(mi.Name, _emptyTypeArray);
                        if (underlyingMi != null)
                        {
                            bool checkedIfConfigured = false;
                            bool isConfigured        = false;
                            foreach (Predicate <MethodInfo> notification in _methodImportsSatisfiedNotifications)
                            {
                                if (notification(underlyingMi))
                                {
                                    if (!checkedIfConfigured)
                                    {
                                        isConfigured        = mi.GetCustomAttributes <OnImportsSatisfiedAttribute>(false).FirstOrDefault() != null;
                                        checkedIfConfigured = true;
                                    }

                                    if (isConfigured)
                                    {
                                        CompositionTrace.Registration_OnSatisfiedImportNotificationOverridden(type, mi);
                                        break;
                                    }
                                    else
                                    {
                                        // We really only need to create this list once and then cache it, it never goes back to null
                                        // Its perfectly okay if we make a list a few times on different threads, effectively though once we have
                                        // cached one we will never make another.
                                        if (s_onImportsSatisfiedAttributeList == null)
                                        {
                                            var onImportsSatisfiedAttributeList = new List <Attribute>
                                            {
                                                new OnImportsSatisfiedAttribute()
                                            };
                                            s_onImportsSatisfiedAttributeList = onImportsSatisfiedAttributeList;
                                        }
                                        configuredMembers.Add(new Tuple <object, List <Attribute> >(mi, s_onImportsSatisfiedAttributeList));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
        public bool IsPartDiscoverable()
        {
            if (this._type.IsAttributeDefined <PartNotDiscoverableAttribute>())
            {
                CompositionTrace.DefinitionMarkedWithPartNotDiscoverableAttribute(this._type);
                return(false);
            }

            if (!HasExports())
            {
                CompositionTrace.DefinitionContainsNoExports(this._type);
                return(false);
            }

            return(true);
        }
Exemplo n.º 7
0
        private static IAttributedImport GetAttributedImport(ReflectionItem item, ICustomAttributeProvider attributeProvider)
        {
            IAttributedImport[] imports = attributeProvider.GetAttributes <IAttributedImport>(false);

            // For constructor parameters they may not have an ImportAttribute
            if (imports.Length == 0)
            {
                return(new ImportAttribute());
            }

            if (imports.Length > 1)
            {
                CompositionTrace.MemberMarkedWithMultipleImportAndImportMany(item);
            }

            // Regardless of how many imports, always return the first one
            return(imports[0]);
        }
Exemplo n.º 8
0
        internal bool BuildConstructorAttributes(Type type, ref List <Tuple <object, List <Attribute> > > configuredMembers)
        {
            IEnumerable <ConstructorInfo> constructors = type.GetTypeInfo().DeclaredConstructors;

            // First see if any of these constructors have the ImportingConstructorAttribute if so then we are already done
            foreach (var ci in constructors)
            {
                // We have a constructor configuration we must log a warning then not bother with ConstructorAttributes
#if netstandard10
                IEnumerable <Attribute> attributes = ci.GetCustomAttributes(typeof(ImportingConstructorAttribute), false);
#else
                IEnumerable <Attribute> attributes = Attribute.GetCustomAttributes(ci, typeof(ImportingConstructorAttribute), false);
#endif
                if (attributes.Count() != 0)
                {
                    CompositionTrace.Registration_ConstructorConventionOverridden(type);
                    return(true);
                }
            }

            if (_constructorFilter != null)
            {
                ConstructorInfo constructorInfo = _constructorFilter(constructors);
                if (constructorInfo != null)
                {
                    ConfigureConstructorAttributes(constructorInfo, ref configuredMembers, _configureConstuctorImports);
                }
                return(true);
            }
            else if (_configureConstuctorImports != null)
            {
                bool configured = false;
                foreach (var constructorInfo in FindLongestConstructors(constructors))
                {
                    ConfigureConstructorAttributes(constructorInfo, ref configuredMembers, _configureConstuctorImports);
                    configured = true;
                }
                return(configured);
            }
            return(false);
        }
Exemplo n.º 9
0
        internal bool BuildConstructorAttributes(Type type, ref List <Tuple <object, List <Attribute> > > configuredMembers)
        {
            ConstructorInfo[] constructors = type.GetConstructors();

            // First see if any of these constructors have the ImportingConstructorAttribute if so then we are already done
            foreach (ConstructorInfo ci in constructors)
            {
                // We have a constructor configuration we must log a warning then not bother with ConstructorAttributes
                object[] attributes = ci.GetCustomAttributes(typeof(ImportingConstructorAttribute), false);
                if (attributes.Length != 0)
                {
                    CompositionTrace.Registration_ConstructorConventionOverridden(type);
                    return(true);
                }
            }

            if (_constructorFilter != null)
            {
                ConstructorInfo constructorInfo = _constructorFilter(constructors);
                if (constructorInfo != null)
                {
                    ConfigureConstructorAttributes(constructorInfo, ref configuredMembers, _configureConstuctorImports);
                }

                return(true);
            }
            else if (_configureConstuctorImports != null)
            {
                bool configured = false;
                foreach (ConstructorInfo constructorInfo in FindLongestConstructors(constructors))
                {
                    ConfigureConstructorAttributes(constructorInfo, ref configuredMembers, _configureConstuctorImports);
                    configured = true;
                }

                return(configured);
            }

            return(false);
        }
        private void UpdateRejections(IEnumerable <ExportDefinition> changedExports, AtomicComposition atomicComposition)
        {
            using (var localAtomicComposition = new AtomicComposition(atomicComposition))
            {
                // Reconsider every part definition that has been previously
                // rejected to see if any of them can be added back.
                var affectedRejections = new HashSet <ComposablePartDefinition>();

                ComposablePartDefinition[] rejectedParts;
                using (_lock.LockStateForRead())
                {
                    rejectedParts = _rejectedParts.ToArray();
                }
                foreach (var definition in rejectedParts)
                {
                    if (QueryPartState(localAtomicComposition, definition) == AtomicCompositionQueryState.TreatAsValidated)
                    {
                        continue;
                    }

                    foreach (var import in definition.ImportDefinitions.Where(ImportEngine.IsRequiredImportForPreview))
                    {
                        if (changedExports.Any(export => import.IsConstraintSatisfiedBy(export)))
                        {
                            affectedRejections.Add(definition);
                            break;
                        }
                    }
                }
                UpdateAtomicCompositionQueryForPartInHashSet(localAtomicComposition,
                                                             affectedRejections, AtomicCompositionQueryState.NeedsTesting);

                // Determine if any of the resurrectable parts is now available so that we can
                // notify listeners of the exact changes to exports
                var resurrectedExports = new List <ExportDefinition>();

                foreach (var partDefinition in affectedRejections)
                {
                    if (!IsRejected(partDefinition, localAtomicComposition))
                    {
                        // Notify listeners of the newly available exports and
                        // prepare to remove the rejected part from the list of rejections
                        resurrectedExports.AddRange(partDefinition.ExportDefinitions);

                        // Capture the local so that the closure below refers to the current definition
                        // in the loop and not the value of 'partDefinition' when the closure executes
                        var capturedPartDefinition = partDefinition;
                        localAtomicComposition.AddCompleteAction(() =>
                        {
                            using (_lock.LockStateForWrite())
                            {
                                _rejectedParts.Remove(capturedPartDefinition);
                            }

                            CompositionTrace.PartDefinitionResurrected(capturedPartDefinition);
                        });
                    }
                }

                // Notify anyone sourcing exports that the resurrected exports have appeared
                if (resurrectedExports.Any())
                {
                    OnExportsChanging(
                        new ExportsChangeEventArgs(resurrectedExports, Array.Empty <ExportDefinition>(), localAtomicComposition));

                    localAtomicComposition.AddCompleteAction(() => OnExportsChanged(
                                                                 new ExportsChangeEventArgs(resurrectedExports, Array.Empty <ExportDefinition>(), null)));
                }

                localAtomicComposition.Complete();
            }
        }
        private bool DetermineRejection(ComposablePartDefinition definition, AtomicComposition parentAtomicComposition)
        {
            ChangeRejectedException exception = null;

            // if there is no active atomic composition and rejection is disabled, there's no need to do any of the below
            if (!EnsureRejection(parentAtomicComposition))
            {
                return(false);
            }

            using (var localAtomicComposition = new AtomicComposition(parentAtomicComposition))
            {
                // The part definition we're currently working on is treated optimistically
                // as if we know it hasn't been rejected.  This handles recursion, and if we
                // later decide that it has been rejected we'll discard all nested progress so
                // all side-effects of the mistake are erased.
                //
                // Note that this means that recursive failures that would be detected by the
                // import engine are not discovered by rejection currently.  Loops among
                // prerequisites, runaway import chains involving factories, and prerequisites
                // that cannot be fully satisfied still result in runtime errors.  Doing
                // otherwise would be possible but potentially expensive - and could be a v2
                // improvement if deemed worthwhile.
                UpdateAtomicCompositionQueryForPartEquals(localAtomicComposition,
                                                          definition, AtomicCompositionQueryState.TreatAsValidated);

                var newPart = definition.CreatePart();
                try
                {
                    _importEngine.PreviewImports(newPart, localAtomicComposition);

                    // Reuse the partially-fleshed out part the next time we need a shared
                    // instance to keep the expense of pre-validation to a minimum.  Note that
                    // _activatedParts holds references to both shared and non-shared parts.
                    // The non-shared parts will only be used for rejection purposes only but
                    // the shared parts will be handed out when requested via GetExports as
                    // well as be used for rejection purposes.
                    localAtomicComposition.AddCompleteActionAllowNull(() =>
                    {
                        using (_lock.LockStateForWrite())
                        {
                            if (!_activatedParts.ContainsKey(definition))
                            {
                                _activatedParts.Add(definition, new CatalogPart(newPart));
                                IDisposable newDisposablePart = newPart as IDisposable;
                                if (newDisposablePart != null)
                                {
                                    _partsToDispose.Add(newDisposablePart);
                                }
                            }
                        }
                    });

                    // Success! Complete any recursive work that was conditioned on this part's validation
                    localAtomicComposition.Complete();

                    return(false);
                }
                catch (ChangeRejectedException ex)
                {
                    exception = ex;
                }
            }

            // If we've reached this point then this part has been rejected so we need to
            // record the rejection in our parent composition or execute it immediately if
            // one doesn't exist.
            parentAtomicComposition.AddCompleteActionAllowNull(() =>
            {
                using (_lock.LockStateForWrite())
                {
                    _rejectedParts.Add(definition);
                }

                CompositionTrace.PartDefinitionRejected(definition, exception);
            });
            if (parentAtomicComposition != null)
            {
                UpdateAtomicCompositionQueryForPartEquals(parentAtomicComposition,
                                                          definition, AtomicCompositionQueryState.TreatAsRejected);
            }

            return(true);
        }
Exemplo n.º 12
0
        internal void BuildPropertyAttributes(Type type, ref List <Tuple <object, List <Attribute> > > configuredMembers)
        {
            if (this._propertyImports.Any() || this._propertyExports.Any())
            {
                foreach (var pi in type.GetRuntimeProperties())
                {
                    List <Attribute> attributes = null;
                    int  importsBuilt           = 0;
                    bool checkedIfConfigured    = false;
                    bool isConfigured           = false;

                    PropertyInfo underlyingPi = null;

                    // Run through the import specifications see if any match
                    foreach (var importSpecification in this._propertyImports)
                    {
                        if (underlyingPi == null)
                        {
                            underlyingPi = pi.DeclaringType.GetRuntimeProperty(pi.Name);
                        }
                        if (importSpecification.Item1 != null && importSpecification.Item1(underlyingPi))
                        {
                            var importBuilder = new ImportConventionBuilder();

                            if (importSpecification.Item2 != null)
                            {
                                importSpecification.Item2(pi, importBuilder);
                            }

                            if (!checkedIfConfigured)
                            {
                                isConfigured        = pi.GetFirstAttribute <ImportAttribute>() != null || pi.GetFirstAttribute <ImportManyAttribute>() != null;
                                checkedIfConfigured = true;
                            }

                            if (isConfigured)
                            {
                                CompositionTrace.Registration_MemberImportConventionOverridden(type, pi);
                                break;
                            }
                            else
                            {
                                importBuilder.BuildAttributes(pi.PropertyType, ref attributes);
                                ++importsBuilt;
                            }
                        }
                        if (importsBuilt > 1)
                        {
                            CompositionTrace.Registration_MemberImportConventionMatchedTwice(type, pi);
                        }
                    }

                    checkedIfConfigured = false;
                    isConfigured        = false;

                    // Run through the export specifications see if any match
                    foreach (var exportSpecification in this._propertyExports)
                    {
                        if (underlyingPi == null)
                        {
                            underlyingPi = pi.DeclaringType.GetRuntimeProperty(pi.Name);
                        }

                        if (exportSpecification.Item1 != null && exportSpecification.Item1(underlyingPi))
                        {
                            var exportBuilder = new ExportConventionBuilder();

                            if (exportSpecification.Item3 != null)
                            {
                                exportBuilder.AsContractType(exportSpecification.Item3);
                            }

                            if (exportSpecification.Item2 != null)
                            {
                                exportSpecification.Item2(pi, exportBuilder);
                            }

                            if (!checkedIfConfigured)
                            {
                                isConfigured        = pi.GetFirstAttribute <ExportAttribute>() != null || MemberHasExportMetadata(pi);
                                checkedIfConfigured = true;
                            }

                            if (isConfigured)
                            {
                                CompositionTrace.Registration_MemberExportConventionOverridden(type, pi);
                                break;
                            }
                            else
                            {
                                exportBuilder.BuildAttributes(pi.PropertyType, ref attributes);
                            }
                        }
                    }

                    if (attributes != null)
                    {
                        if (configuredMembers == null)
                        {
                            configuredMembers = new List <Tuple <object, List <Attribute> > >();
                        }

                        configuredMembers.Add(Tuple.Create((object)pi, attributes));
                    }
                }
            }
            return;
        }
Exemplo n.º 13
0
        internal IEnumerable <Attribute> BuildTypeAttributes(Type type)
        {
            var attributes = new List <Attribute>();

            if (this._typeExportBuilders != null)
            {
                bool isConfigured = type.GetTypeInfo().GetFirstAttribute <ExportAttribute>() != null || MemberHasExportMetadata(type.GetTypeInfo());
                if (isConfigured)
                {
                    CompositionTrace.Registration_TypeExportConventionOverridden(type);
                }
                else
                {
                    foreach (var export in this._typeExportBuilders)
                    {
                        export.BuildAttributes(type, ref attributes);
                    }
                }
            }

            if (this._isShared)
            {
                // Check if there is already a SharedAttribute.  If found Trace a warning and do not add this Shared
                // otherwise add new one
                bool isConfigured = type.GetTypeInfo().GetFirstAttribute <SharedAttribute>() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_PartCreationConventionOverridden(type);
                }
                else
                {
                    attributes.Add(this._sharingBoundary == null ?
                                   new SharedAttribute() :
                                   new SharedAttribute(this._sharingBoundary));
                }
            }

            //Add metadata attributes from direct specification
            if (this._metadataItems != null)
            {
                bool isConfigured = type.GetTypeInfo().GetFirstAttribute <PartMetadataAttribute>() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_PartMetadataConventionOverridden(type);
                }
                else
                {
                    foreach (var item in this._metadataItems)
                    {
                        attributes.Add(new PartMetadataAttribute(item.Item1, item.Item2));
                    }
                }
            }

            //Add metadata attributes from func specification
            if (this._metadataItemFuncs != null)
            {
                bool isConfigured = type.GetTypeInfo().GetFirstAttribute <PartMetadataAttribute>() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_PartMetadataConventionOverridden(type);
                }
                else
                {
                    foreach (var item in this._metadataItemFuncs)
                    {
                        var name  = item.Item1;
                        var value = (item.Item2 != null) ? item.Item2(type) : null;
                        attributes.Add(new PartMetadataAttribute(name, value));
                    }
                }
            }

            if (this._interfaceExports.Any())
            {
                if (this._typeExportBuilders != null)
                {
                    bool isConfigured = type.GetTypeInfo().GetFirstAttribute <ExportAttribute>() != null || MemberHasExportMetadata(type.GetTypeInfo());
                    if (isConfigured)
                    {
                        CompositionTrace.Registration_TypeExportConventionOverridden(type);
                    }
                    else
                    {
                        foreach (var iface in type.GetTypeInfo().ImplementedInterfaces)
                        {
                            if (iface == typeof(IDisposable))
                            {
                                continue;
                            }

                            // Run through the export specifications see if any match
                            foreach (var exportSpecification in this._interfaceExports)
                            {
                                if (exportSpecification.Item1 != null && exportSpecification.Item1(iface))
                                {
                                    ExportConventionBuilder exportBuilder = new ExportConventionBuilder();
                                    exportBuilder.AsContractType(iface);
                                    if (exportSpecification.Item2 != null)
                                    {
                                        exportSpecification.Item2(iface, exportBuilder);
                                    }
                                    exportBuilder.BuildAttributes(iface, ref attributes);
                                }
                            }
                        }
                    }
                }
            }
            return(attributes);
        }
Exemplo n.º 14
0
        internal void BuildPropertyAttributes(Type type, ref List <Tuple <object, List <Attribute> > > configuredMembers)
        {
            if (_propertyImports.Any() || _propertyExports.Any())
            {
                foreach (PropertyInfo pi in type.GetProperties())
                {
                    List <Attribute> attributes = null;
                    PropertyInfo     declaredPi = pi.DeclaringType.UnderlyingSystemType.GetProperty(pi.Name, pi.PropertyType);
                    int  importsBuilt           = 0;
                    bool checkedIfConfigured    = false;
                    bool isConfigured           = false;

                    // Run through the import specifications see if any match
                    foreach (Tuple <Predicate <PropertyInfo>, Action <PropertyInfo, ImportBuilder>, Type> importSpecification in _propertyImports)
                    {
                        if (importSpecification.Item1 != null && importSpecification.Item1(declaredPi))
                        {
                            var importBuilder = new ImportBuilder();

                            if (importSpecification.Item3 != null)
                            {
                                importBuilder.AsContractType(importSpecification.Item3);
                            }

                            importSpecification.Item2?.Invoke(declaredPi, importBuilder);

                            if (!checkedIfConfigured)
                            {
                                isConfigured        = pi.GetCustomAttributes(typeof(ImportAttribute), false).FirstOrDefault() != null || pi.GetCustomAttributes(typeof(ImportManyAttribute), false).FirstOrDefault() != null;
                                checkedIfConfigured = true;
                            }

                            if (isConfigured)
                            {
                                CompositionTrace.Registration_MemberImportConventionOverridden(type, pi);
                                break;
                            }
                            else
                            {
                                importBuilder.BuildAttributes(declaredPi.PropertyType, ref attributes);
                                ++importsBuilt;
                            }
                        }
                        if (importsBuilt > 1)
                        {
                            CompositionTrace.Registration_MemberImportConventionMatchedTwice(type, pi);
                        }
                    }

                    checkedIfConfigured = false;
                    isConfigured        = false;

                    // Run through the export specifications see if any match
                    foreach (Tuple <Predicate <PropertyInfo>, Action <PropertyInfo, ExportBuilder>, Type> exportSpecification in _propertyExports)
                    {
                        if (exportSpecification.Item1 != null && exportSpecification.Item1(declaredPi))
                        {
                            var exportBuilder = new ExportBuilder();

                            if (exportSpecification.Item3 != null)
                            {
                                exportBuilder.AsContractType(exportSpecification.Item3);
                            }

                            exportSpecification.Item2?.Invoke(declaredPi, exportBuilder);

                            if (!checkedIfConfigured)
                            {
                                isConfigured        = pi.GetCustomAttributes(typeof(ExportAttribute), false).FirstOrDefault() != null || MemberHasExportMetadata(pi);
                                checkedIfConfigured = true;
                            }

                            if (isConfigured)
                            {
                                CompositionTrace.Registration_MemberExportConventionOverridden(type, pi);
                                break;
                            }
                            else
                            {
                                exportBuilder.BuildAttributes(declaredPi.PropertyType, ref attributes);
                            }
                        }
                    }

                    if (attributes != null)
                    {
                        if (configuredMembers == null)
                        {
                            configuredMembers = new List <Tuple <object, List <Attribute> > >();
                        }

                        configuredMembers.Add(Tuple.Create((object)declaredPi, attributes));
                    }
                }
            }
        }
Exemplo n.º 15
0
        internal IEnumerable <Attribute> BuildTypeAttributes(Type type)
        {
            var attributes = new List <Attribute>();

            if (_typeExportBuilders != null)
            {
                bool isConfigured = type.GetCustomAttributes(typeof(ExportAttribute), false).FirstOrDefault() != null || MemberHasExportMetadata(type);
                if (isConfigured)
                {
                    CompositionTrace.Registration_TypeExportConventionOverridden(type);
                }
                else
                {
                    foreach (ExportBuilder export in _typeExportBuilders)
                    {
                        export.BuildAttributes(type, ref attributes);
                    }
                }
            }

            if (_setCreationPolicy)
            {
                // Check if there is already a PartCreationPolicyAttribute
                // If found Trace a warning and do not add the registered part creationpolicy
                // otherwise add new one
                bool isConfigured = type.GetCustomAttributes(typeof(PartCreationPolicyAttribute), false).FirstOrDefault() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_PartCreationConventionOverridden(type);
                }
                else
                {
                    attributes.Add(new PartCreationPolicyAttribute(_creationPolicy));
                }
            }

            //Add metadata attributes from direct specification
            if (_metadataItems != null)
            {
                bool isConfigured = type.GetCustomAttributes(typeof(PartMetadataAttribute), false).FirstOrDefault() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_PartMetadataConventionOverridden(type);
                }
                else
                {
                    foreach (Tuple <string, object> item in _metadataItems)
                    {
                        attributes.Add(new PartMetadataAttribute(item.Item1, item.Item2));
                    }
                }
            }

            //Add metadata attributes from func specification
            if (_metadataItemFuncs != null)
            {
                bool isConfigured = type.GetCustomAttributes(typeof(PartMetadataAttribute), false).FirstOrDefault() != null;
                if (isConfigured)
                {
                    CompositionTrace.Registration_PartMetadataConventionOverridden(type);
                }
                else
                {
                    foreach (Tuple <string, Func <Type, object> > item in _metadataItemFuncs)
                    {
                        var name  = item.Item1;
                        var value = (item.Item2 != null) ? item.Item2(type) : null;
                        attributes.Add(new PartMetadataAttribute(name, value));
                    }
                }
            }

            if (_interfaceExports.Any())
            {
                if (_typeExportBuilders != null)
                {
                    bool isConfigured = type.GetCustomAttributes(typeof(ExportAttribute), false).FirstOrDefault() != null || MemberHasExportMetadata(type);
                    if (isConfigured)
                    {
                        CompositionTrace.Registration_TypeExportConventionOverridden(type);
                    }
                    else
                    {
                        foreach (Type iface in type.GetInterfaces())
                        {
                            Type underlyingType = iface.UnderlyingSystemType;

                            if (underlyingType == typeof(IDisposable) || underlyingType == typeof(IPartImportsSatisfiedNotification))
                            {
                                continue;
                            }

                            // Run through the export specifications see if any match
                            foreach (Tuple <Predicate <Type>, Action <Type, ExportBuilder> > exportSpecification in _interfaceExports)
                            {
                                if (exportSpecification.Item1 != null && exportSpecification.Item1(underlyingType))
                                {
                                    ExportBuilder exportBuilder = new ExportBuilder();
                                    exportBuilder.AsContractType((Type)iface);
                                    exportSpecification.Item2?.Invoke(iface, exportBuilder);
                                    exportBuilder.BuildAttributes(iface, ref attributes);
                                }
                            }
                        }
                    }
                }
            }

            return(attributes);
        }