示例#1
0
        /// <summary>
        /// Adds one or more directory paths to be searched for assemblies
        /// that are to be inspected for any matching assemblies when resolving
        /// for components.
        /// </summary>
        /// <param name="configuration">the configuration to add paths to</param>
        /// <param name="paths">one or more paths to include in the search</param>
        /// <param name="searchOption">specifies to search either for top-level directories
        ///             only or to descend into child dirs too</param>
        /// <param name="patterns">one or more wildcard patterns to search for;
        ///             defaults to '*.dll'</param>
        /// <returns></returns>
        /// <remarks>
        /// Based on:
        ///    http://weblogs.asp.net/ricardoperes/using-mef-in-net-core
        /// </remarks>
        public static ContainerConfiguration WithAssembliesInPaths(
            this ContainerConfiguration configuration,
            IEnumerable <string> paths,
            AttributedModelProvider conventions = null,
            SearchOption searchOption           = SearchOption.TopDirectoryOnly,
            IEnumerable <string> patterns       = null)
        {
            if (patterns == null)
            {
                patterns = DEFAULT_PATTERNS;
            }

            foreach (var p in paths)
            {
                foreach (var r in patterns)
                {
                    var assemblies = Directory
                                     .GetFiles(p, r, searchOption)
                                     .Select(AssemblyLoadContext.Default.LoadFromAssemblyPath)
                                     // TODO:  This didn't seem to work, LoadFromAsmName kept throwing
                                     // FileNotFoundException even though the AsmName was legit
                                     // .Select(AssemblyLoadContext.GetAssemblyName)
                                     // .Select(AssemblyLoadContext.Default.LoadFromAssemblyName)
                                     .ToList();

                    configuration.WithAssemblies(assemblies, conventions);
                }
            }

            return(configuration);
        }
示例#2
0
        private static ContainerConfiguration WithAssembliesInPath(ContainerConfiguration configuration,
                                                                   string path, AttributedModelProvider conventions,
                                                                   SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            var assemblies     = new List <Assembly>();
            var assemblieFiles = Directory.GetFiles(path, "*.dll", searchOption);

            foreach (var assemblyFile in assemblieFiles)
            {
                try
                {
                    var ctx = new MarvinAssemblyLoadContext();
                    AssemblyLoadContext.InitializeDefaultContext(ctx);

                    var name = AssemblyLoadContext.GetAssemblyName(assemblyFile);
                    var asm  = Assembly.Load(name);

                    assemblies.Add(asm);
                }
                catch (Exception e)
                {
                    Console.Out.WriteLine("Error loading module: " + e.Message + " from: " + path);
                }
            }

            return(configuration.WithAssemblies(assemblies, conventions));
        }
示例#3
0
        /// <summary>
        /// Adds one or more directory paths to be searched for assemblies
        /// that are to be inspected for any matching assemblies when resolving
        /// for components.
        /// </summary>
        /// <param name="configuration">the configuration to add paths to</param>
        /// <param name="paths">one or more paths to include in the search</param>
        /// <param name="searchOption">specifies to search either for top-level directories
        ///             only or to descend into child dirs too</param>
        /// <param name="patterns">one or more wildcard patterns to search for;
        ///             defaults to '*.dll'</param>
        /// <returns></returns>
        /// <remarks>
        /// Based on:
        ///    http://weblogs.asp.net/ricardoperes/using-mef-in-net-core
        /// </remarks>
        public static ContainerConfiguration WithAssembliesInPaths(
            this ContainerConfiguration configuration,
            IEnumerable <string> paths,
            AttributedModelProvider conventions = null,
            SearchOption searchOption           = SearchOption.TopDirectoryOnly,
            IEnumerable <string> patterns       = null)
        {
            if (patterns == null)
            {
                patterns = DEFAULT_PATTERNS;
            }

            foreach (var p in paths)
            {
                foreach (var r in patterns)
                {
                    var assemblies = Directory
                                     .GetFiles(p, r, searchOption)
                                     .Select(LoadFromAssembly)
                                     .Where(x => x != null)
                                     .ToList();

                    configuration.WithAssemblies(assemblies, conventions);
                }
            }

            return(configuration);
        }
示例#4
0
 /// <summary>
 /// Constructor. Notice that the default <paramref name="handleNewExports"/> delegate
 /// will always compose all Assemblies on every event sequence, and add all new Exports that
 /// do not compare value-equal to any existing Export. You may prefer to filter either the
 /// Assemblies or the composed Exports.
 /// Notice also, this class extends <see cref="Composer{TTarget}"/>, and this by
 /// default sets <see cref="Composer{TTarget}.ComposeExceptionPolicy"/> to
 /// <see cref="ComposerExceptionPolicy.ThrowNone"/>.
 /// </summary>
 /// <param name="exportTypes">Required: defines the Exports that will be composed on
 /// each event. All Exports of each type here are fetched from the
 /// <see cref="CompositionHost"/> that is constructed in the
 /// <see cref="Composer{TTarget}.GetTarget"/> handler; and these objects are added to
 /// the <see cref="ExportsList"/> (or handled by your handler).</param>
 /// <param name="defaultConventions">Optional conventions used on each composition to construct each
 /// <see cref="ContainerConfiguration"/>.</param>
 /// <param name="disposeCompositionHostsWithThis">Specifies how all created
 /// <see cref="CompositionHost"/> instances are handled when this object is disposed: notice
 /// that this defaults to true --- when disposed, the contained exports may be disposed. If
 /// not disposed, the references are simply dropped.</param>
 /// <param name="disposeProvidersWithThis">Specifies how added PROVIDERS are handled when
 /// this object is disposed: notice that this defaults to true.</param>
 /// <param name="handleNewExports">An optional handler that is invoked on every composition, which
 /// does all the work of adding new Exports, and potentially removing (and Disposing) existing
 /// Exports. This composer will perform a part composition event sequence, and then it invokes this
 /// delegate. The first argument is mutable, and contains the current <see cref="ExportsList"/>.
 /// You must directly modify this list as desired. If you remove any elements, you must handle
 /// any disposal yourself. The second argument contains the new Exports composed on this composition
 /// event. You must add any desired elements. These new Exports are constructed in a new
 /// <see cref="CompositionHost"/>, which is retained if you retain any of these objects, and
 /// otherwise will be disposed immediately after invoking this delegate. You should only dispose
 /// any new Exports that you do not add if you are able to safely do so, and
 /// if the disposal of that transient <see cref="CompositionHost"/> will not be sufficient. If
 /// you don't provide this delegate, the composer always adds any new Exports that do not compare
 /// value-equal to any existing Export, and will NOT dispose any new Exports that were not
 /// added --- it presumes that the disposal of that transient <see cref="CompositionHost"/>
 /// is sufficient, and prevents disposing objects that may be linked in a graph. Your delegate
 /// also returns an Action: this may be null, and if not null, it is invoked after the
 /// mutation is complete. This delegate is invoked on the
 /// <see cref="Composer{TTarget}.WithAllParts"/> event --- after all
 /// <see cref="IProvideParts{TTarget}"/> callbacks, and before
 /// <see cref="IBootstrap{TTarget}"/>.</param>
 public MefSingletonComposer(
     IEnumerable <Type> exportTypes,
     AttributedModelProvider defaultConventions,
     bool disposeCompositionHostsWithThis = true,
     bool disposeProvidersWithThis        = true,
     Func <List <object>, IReadOnlyList <object>, Action> handleNewExports = null)
     : base(defaultConventions, disposeProvidersWithThis)
 {
     if (exportTypes == null)
     {
         throw new ArgumentNullException(nameof(exportTypes));
     }
     ExportTypes = exportTypes.ToArray();
     if (ExportTypes.Count == 0)
     {
         throw new ArgumentException(nameof(exportTypes));
     }
     this.disposeCompositionHostsWithThis = disposeCompositionHostsWithThis;
     this.handleNewExports = handleNewExports ?? HandleNewExports;
     Action HandleNewExports(List <object> exportsList, IReadOnlyList <object> newExports)
     {
         foreach (object newExport in newExports)
         {
             if (!exportsList.Contains(newExport))
             {
                 exportsList.Add(newExport);
             }
         }
         return(null);
     }
 }
        public static ContainerConfiguration WithAssembliesByPath
        (
            this ContainerConfiguration configuration
            , string path
            , AttributedModelProvider conventions
            , SearchOption searchOption = SearchOption.TopDirectoryOnly
        )
        {
            var assemblies = Directory
                             .GetFiles(path, "*.dll", searchOption)
                             //.Select
                             //    (
                             //        (x) =>
                             //        {
                             //            return
                             //            AssemblyLoadContext.GetAssemblyName(x);
                             //        }
                             //    )
                             .Select
                             (
                (x) =>
            {
                return
                (AssemblyLoadContext
                 .Default
                 .LoadFromAssemblyPath(x));
            }
                             )
                             .ToList();

            configuration = configuration.WithAssemblies(assemblies, conventions);

            return(configuration);
        }
        public static ContainerConfiguration WithPrivateAssemblies( this ContainerConfiguration configuration, AttributedModelProvider conventions )
        {
            Arg.NotNull( configuration, nameof( configuration ) );
            Contract.Ensures( Contract.Result<ContainerConfiguration>() != null );

            var relativeSearchPath = AppDomain.CurrentDomain.RelativeSearchPath;

            // exit if no probing path for private assemblies is defined
            if ( string.IsNullOrEmpty( relativeSearchPath ) )
                return configuration;

            var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;

            // find all libraries defined in probing paths
            var assemblyFiles = from relativePath in relativeSearchPath.Split( new[] { ';' }, StringSplitOptions.RemoveEmptyEntries )
                                let path = Path.Combine( baseDirectory, relativePath )
                                where Directory.Exists( path )
                                from dll in Directory.GetFiles( path, "*.dll" )
                                select dll;

            // get assemblies from paths
            var assemblies = from file in assemblyFiles
                             let name = AssemblyName.GetAssemblyName( file )
                             select Assembly.Load( name );

            // add all assemblies to the configuration
            configuration.WithAssemblies( assemblies, conventions );

            return configuration;
        }
        public static ContainerConfiguration WithAssembliesInPath(
            this ContainerConfiguration configuration,
            IEnumerable <string> paths,
            AttributedModelProvider conventions = null,
            SearchOption searchOption           = SearchOption.TopDirectoryOnly,
            string[] patterns = null)
        {
            if (patterns == null)
            {
                patterns = DefaultPatterns;
            }

            foreach (string path in paths)
            {
                foreach (string pattern in patterns)
                {
                    // Load assemblies from path
                    List <Assembly> assemblies = Directory
                                                 .GetFiles(path, pattern, searchOption)
                                                 .Select(LoadFromAssembly)
                                                 .Where(x => x != null)
                                                 .ToList();

                    configuration.WithAssemblies(assemblies, conventions);
                }
            }

            return(configuration);
        }
 public OnImportsSatisfiedFeature(AttributedModelProvider attributeContext)
 {
     if (attributeContext == null)
     {
         throw new ArgumentNullException(nameof(attributeContext));
     }
     _attributeContext = attributeContext;
 }
        public MefDependencyResolver(AttributedModelProvider builder, IDependencyResolver resolver)
        {
            _container = new ContainerConfiguration()
                         .WithAssemblies(AppDomain.CurrentDomain.GetAssemblies(), builder)
                         .CreateContainer();

            _resolver = resolver;
        }
 /// <summary>
 /// Add a part type to the container. If the part type does not have any exports it
 /// will be ignored.
 /// </summary>
 /// <param name="partType">The part type.</param>
 /// <param name="conventions">Conventions represented by a <see cref="AttributedModelProvider"/>, or null.</param>
 /// <returns>A configuration object allowing configuration to continue.</returns>
 public ContainerConfiguration WithPart(Type partType, AttributedModelProvider conventions)
 {
     if (partType == null)
     {
         throw new ArgumentNullException(nameof(partType));
     }
     return(WithParts(new[] { partType }, conventions));
 }
示例#11
0
 /// <summary>
 /// Add part types to the container. If a part type does not have any exports it
 /// will be ignored.
 /// </summary>
 /// <param name="partTypes">The part types.</param>
 /// <param name="conventions">Conventions represented by a <see cref="AttributedModelProvider"/>, or null.</param>
 /// <returns>A configuration object allowing configuration to continue.</returns>
 public ContainerConfiguration WithParts(IEnumerable <Type> partTypes, AttributedModelProvider conventions)
 {
     if (partTypes == null)
     {
         throw new ArgumentNullException("partTypes");
     }
     _types.Add(Tuple.Create(partTypes, conventions));
     return(this);
 }
示例#12
0
        public static ContainerConfiguration WithAssembliesInPath(this ContainerConfiguration configuration,
                                                                  string path, AttributedModelProvider conventions, SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            var assemblyFiles = Directory.GetFiles(path, "*.dll", searchOption);
            var assemblies    = assemblyFiles.Select(AssemblyLoadContext.Default.LoadFromAssemblyPath);

            configuration = configuration.WithAssemblies(assemblies, conventions);
            return(configuration);
        }
 static ActivationFeature[] CreateActivationFeatures(AttributedModelProvider attributeContext)
 {
     return(new ActivationFeature[] {
         new DisposalFeature(),
         new PropertyInjectionFeature(attributeContext),
         new OnImportsSatisfiedFeature(attributeContext),
         new LifetimeFeature(),
     });
 }
示例#14
0
 public DiscoveredPart(
     TypeInfo partType,
     AttributedModelProvider attributeContext,
     ActivationFeature[] activationFeatures)
 {
     _partType           = partType;
     _attributeContext   = attributeContext;
     _activationFeatures = activationFeatures;
     _partMetadata       = new Lazy <IDictionary <string, object> >(() => GetPartMetadata(partType));
 }
示例#15
0
        /// <summary>
        /// Add conventions defined using a <see cref="AttributedModelProvider"/> to the container.
        /// These will be used as the default conventions; types and assemblies added with a
        /// specific convention will use their own.
        /// </summary>
        /// <param name="conventions"></param>
        /// <returns>A configuration object allowing configuration to continue.</returns>
        public ContainerConfiguration WithDefaultConventions(AttributedModelProvider conventions)
        {
            if (conventions == null) throw new ArgumentNullException("conventions");

            if (_defaultAttributeContext != null)
                throw new InvalidOperationException(System.Composition.Properties.Resources.ContainerConfiguration_DefaultConventionSet);

            _defaultAttributeContext = conventions;
            return this;
        }
示例#16
0
 private DiscoveredPart(
     TypeInfo partType,
     AttributedModelProvider attributeContext,
     ActivationFeature[] activationFeatures,
     Lazy <IDictionary <string, object> > partMetadata)
 {
     _partType           = partType;
     _attributeContext   = attributeContext;
     _activationFeatures = activationFeatures;
     _partMetadata       = partMetadata;
 }
示例#17
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="directoryWatcher">Not null.</param>
 /// <param name="searchOption">Optional search option to locate Assemblies: defaults to
 /// <see cref="System.IO.SearchOption.TopDirectoryOnly"/>.</param>
 /// <param name="conventions">Optional conventions applied to all added
 /// Assemblies.</param>
 /// <exception cref="ArgumentNullException"></exception>
 public MefDirectoryPartWatcher(
     DirectoryWatcher directoryWatcher,
     SearchOption searchOption           = SearchOption.TopDirectoryOnly,
     AttributedModelProvider conventions = null)
     : this(
         null,
         false,
         directoryWatcher,
         searchOption,
         conventions)
 {
 }
示例#18
0
 /// <summary>
 /// This constructor creates a new <see cref="IO.Files.DirectoryWatcher"/>.
 /// This constructs the instance with your <c>path</c>, and sets the file filter to
 /// <c>"*.dll"</c>. The default <see cref="NotifyFilters"/> are used,
 /// and subdirectories are not included by default.
 /// </summary>
 /// <param name="path">Required: must be a valid directory path..</param>
 /// <param name="searchOption">Optional search option to locate Assemblies: defaults to
 /// <see cref="System.IO.SearchOption.TopDirectoryOnly"/>.</param>
 /// <param name="conventions">Optional conventions applied to all added
 /// Assemblies.</param>
 /// <exception cref="ArgumentNullException">For <c>path</c>.</exception>
 /// <exception cref="ArgumentException">For <c>path</c>.</exception>
 /// <exception cref="SecurityException">For <c>path</c>.</exception>
 /// <exception cref="ArgumentNullException">For <c>path</c>.</exception>
 /// <exception cref="NotSupportedException">For <c>path</c>.</exception>
 /// <exception cref="PathTooLongException">For <c>path</c>.</exception>
 public MefDirectoryPartWatcher(
     string path,
     SearchOption searchOption           = SearchOption.TopDirectoryOnly,
     AttributedModelProvider conventions = null)
     : this(
         null,
         false,
         new DirectoryWatcher(path, "*.dll", searchOption == SearchOption.AllDirectories),
         searchOption,
         conventions)
 {
 }
示例#19
0
 /// <summary>
 /// Constructor. Allows passing a delegate that is used to load each Assembly,
 /// </summary>
 /// <param name="loadAssembly">Not null. This Func is passed the full path to each Assembly
 /// to load. You may return null if the Assembly cannot be loaded; and exceptions will
 /// be caught and traced.</param>
 /// <param name="directoryWatcher">Not null.</param>
 /// <param name="searchOption">Optional search option to locate Assemblies: defaults to
 /// <see cref="System.IO.SearchOption.TopDirectoryOnly"/>.</param>
 /// <param name="conventions">Optional conventions applied to all added
 /// Assemblies.</param>
 /// <exception cref="ArgumentNullException"></exception>
 public MefDirectoryPartWatcher(
     Func <string, Assembly> loadAssembly,
     DirectoryWatcher directoryWatcher,
     SearchOption searchOption           = SearchOption.TopDirectoryOnly,
     AttributedModelProvider conventions = null)
     : this(
         loadAssembly,
         true,
         directoryWatcher,
         searchOption,
         conventions)
 {
 }
示例#20
0
        MvcContainerConfiguration(IEnumerable <Assembly> assemblies, AttributedModelProvider reflectionContext)
        {
            if (assemblies == null)
            {
                throw new ArgumentNullException("assemblies");
            }
            if (reflectionContext == null)
            {
                throw new ArgumentNullException("reflectionContext");
            }

            this.WithDefaultConventions(reflectionContext);
            this.WithAssemblies(assemblies);
        }
        public TypedPartExportDescriptorProvider(IEnumerable <Type> types, AttributedModelProvider attributeContext)
        {
            var activationFeatures = CreateActivationFeatures(attributeContext);
            var typeInspector      = new TypeInspector(attributeContext, activationFeatures);

            foreach (var type in types)
            {
                DiscoveredPart part;
                if (typeInspector.InspectTypeForPart(type.GetTypeInfo(), out part))
                {
                    AddDiscoveredPart(part);
                }
            }
        }
        /// <summary>
        /// Add conventions defined using a <see cref="AttributedModelProvider"/> to the container.
        /// These will be used as the default conventions; types and assemblies added with a
        /// specific convention will use their own.
        /// </summary>
        /// <param name="conventions"></param>
        /// <returns>A configuration object allowing configuration to continue.</returns>
        public ContainerConfiguration WithDefaultConventions(AttributedModelProvider conventions)
        {
            if (conventions is null)
            {
                throw new ArgumentNullException(nameof(conventions));
            }

            if (_defaultAttributeContext != null)
            {
                throw new InvalidOperationException(SR.ContainerConfiguration_DefaultConventionSet);
            }

            _defaultAttributeContext = conventions;
            return(this);
        }
示例#23
0
        // Based on:
        //    http://weblogs.asp.net/ricardoperes/using-mef-in-net-core
        internal static ContainerConfiguration WithAssembliesInPath(
            this ContainerConfiguration configuration, string path,
            AttributedModelProvider conventions,
            SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            var assemblies = Directory
                             .GetFiles(path, "*.dll", searchOption)
                             .Select(AssemblyLoadContext.Default.LoadFromAssemblyPath)
                             // TODO:  This didn't seem to work, LoadFromAsmName kept throwing
                             // FileNotFoundException even though the AsmName was legit
                             // .Select(AssemblyLoadContext.GetAssemblyName)
                             // .Select(AssemblyLoadContext.Default.LoadFromAssemblyName)
                             .ToList();

            configuration.WithAssemblies(assemblies, conventions);

            return(configuration);
        }
示例#24
0
 private MefDirectoryPartWatcher(
     Func <string, Assembly> loadAssembly,
     bool requireLoadAssembly,
     DirectoryWatcher directoryWatcher,
     SearchOption searchOption,
     AttributedModelProvider conventions)
 {
     if (requireLoadAssembly &&
         (loadAssembly == null))
     {
         throw new ArgumentNullException(nameof(loadAssembly));
     }
     this.loadAssembly         = loadAssembly;
     DirectoryWatcher          = directoryWatcher ?? throw new ArgumentNullException(nameof(directoryWatcher));
     SearchOption              = searchOption;
     Conventions               = conventions;
     DirectoryWatcher.Changed += HandleDirectoryWatcherChanged;
 }
示例#25
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="providedAssemblies">May not be null or empty.</param>
 /// <param name="conventions">Optional conventions applied to all added
 /// Assemblies.</param>
 /// <exception cref="ArgumentNullException"></exception>
 /// <exception cref="ArgumentException"></exception>
 public MefAssemblyPartProvider(
     IEnumerable <Assembly> providedAssemblies,
     AttributedModelProvider conventions = null)
 {
     ProvidedAssemblies
         = providedAssemblies?.ToArray()
           ?? throw new ArgumentNullException(nameof(providedAssemblies));
     if (ProvidedAssemblies.Count == 0)
     {
         throw new ArgumentException(nameof(providedAssemblies));
     }
     foreach (Assembly providedAssembly in ProvidedAssemblies)
     {
         if (providedAssembly == null)
         {
             throw new ArgumentException(nameof(providedAssemblies));
         }
     }
     Conventions = conventions;
 }
示例#26
0
        public MefDependencyResolver(AttributedModelProvider builder, IDependencyResolver resolver)
        {
            var searchPath = HttpRuntime.BinDirectory;

            XTrace.WriteLine("Addions search path: {0}", searchPath);

            var addions = Directory.GetFiles(searchPath, "gitcandy.*.dll")
                          .Select(x => Assembly.Load(File.ReadAllBytes(x)))
                          .ToList();

            XTrace.WriteLine("It is found {0} DLLs for resloving addion: {1}",
                             addions.Count,
                             string.Concat(addions.Select(x => x.GetName().Name + " ").ToArray()));

            _container = new ContainerConfiguration()
                         .WithAssembly(Assembly.GetCallingAssembly(), builder)
                         .WithAssemblies(addions, builder)
                         .CreateContainer();

            _resolver = resolver;
        }
 internal static ActivationFeature[] DebugGetActivationFeatures(AttributedModelProvider attributeContext)
 {
     return(CreateActivationFeatures(attributeContext));
 }
        public static ContainerConfiguration WithAppDomain( this ContainerConfiguration configuration, AttributedModelProvider conventions )
        {
            Arg.NotNull( configuration, nameof( configuration ) );
            Contract.Ensures( Contract.Result<ContainerConfiguration>() != null );

            // find all the executables and libraries in the current base directory
            var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
            var assemblyFiles = Directory.GetFiles( baseDirectory, "*.exe" ).Union( Directory.GetFiles( baseDirectory, "*.dll" ) );
            var assemblies = from file in assemblyFiles
                             let name = AssemblyName.GetAssemblyName( file )
                             select Assembly.Load( name );

            // add all assemblies to the configuration
            configuration.WithAssemblies( assemblies, conventions );
            configuration.WithPrivateAssemblies( conventions );

            return configuration;
        }
        public static ContainerConfiguration WithAssembliesInPath(this ContainerConfiguration configuration, string path, string searchPattern, AttributedModelProvider conventions, SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return(configuration);
            }

            var assemblies = Directory
                             .GetFiles(path, searchPattern, searchOption)
                             .Select(AssemblyLoadContext.GetAssemblyName)
                             .Select(AssemblyLoadContext.Default.LoadFromAssemblyName)
                             .ToList();

            configuration = configuration.WithAssemblies(assemblies, conventions);

            return(configuration);
        }
示例#30
0
 public TypeInspector(AttributedModelProvider attributeContext, ActivationFeature[] activationFeatures)
 {
     _attributeContext   = attributeContext;
     _activationFeatures = activationFeatures;
 }
 /// <summary>
 /// Add part types from an assembly to the container. If a part type does not have any exports it
 /// will be ignored.
 /// </summary>
 /// <param name="assembly">The assembly from which to add part types.</param>
 /// <param name="conventions">Conventions represented by a <see cref="AttributedModelProvider"/>, or null.</param>
 /// <returns>A configuration object allowing configuration to continue.</returns>
 public ContainerConfiguration WithAssembly(Assembly assembly, AttributedModelProvider conventions)
 {
     return(WithAssemblies(new[] { assembly }, conventions));
 }
        /// <summary>
        /// Add part types from a list of assemblies to the container. If a part type does not have any exports it
        /// will be ignored.
        /// </summary>
        /// <param name="assemblies">Assemblies containing part types.</param>
        /// <param name="conventions">Conventions represented by a <see cref="AttributedModelProvider"/>, or null.</param>
        /// <returns>A configuration object allowing configuration to continue.</returns>
        public ContainerConfiguration WithAssemblies(IEnumerable <Assembly> assemblies, AttributedModelProvider conventions)
        {
            if (assemblies is null)
            {
                throw new ArgumentNullException(nameof(assemblies));
            }

            return(WithParts(assemblies.SelectMany(a => a.DefinedTypes.Select(dt => dt.AsType())), conventions));
        }