// ----------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // ----------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel.Composition.Primitives; using System.ComponentModel.Composition.ReflectionModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Security; using System.Threading; using Microsoft.Internal; namespace System.ComponentModel.Composition.Hosting { /// /// An immutable ComposablePartCatalog created from a managed code assembly. /// /// /// This type is thread safe. /// [DebuggerTypeProxy(typeof(AssemblyCatalogDebuggerProxy))] public class AssemblyCatalog : ComposablePartCatalog, ICompositionElement { private readonly object _thisLock = new object(); private readonly ICompositionElement _definitionOrigin; private volatile Assembly _assembly = null; private volatile TypeCatalog _innerCatalog = null; private int _isDisposed = 0; #if !SILVERLIGHT /// /// Initializes a new instance of the class /// with the specified code base. /// /// /// A containing the code base of the assembly containing the /// attributed objects to add to the . /// /// /// is . /// /// /// is a zero-length string, contains only white space, /// or contains one or more invalid characters as defined by . /// /// /// The specified path, file name, or both exceed the system-defined maximum length. /// /// /// The caller does not have path discovery permission. /// /// /// is not found. /// /// /// could not be loaded. /// /// -or- /// /// specified a directory. /// /// /// is not a valid assembly /// -or- /// Version 2.0 or later of the common language runtime is currently loaded /// and was compiled with a later version. /// /// /// The assembly referenced by is loaded into the Load context. /// public AssemblyCatalog(string codeBase) : this(codeBase, (ICompositionElement)null) { } internal AssemblyCatalog(string codeBase, ICompositionElement definitionOrigin) : this(LoadAssembly(codeBase), definitionOrigin) { } #endif /// /// Initializes a new instance of the class /// with the specified assembly. /// /// /// The containing the attributed objects to /// add to the . /// /// /// is . /// /// -or- /// /// was loaded in the reflection-only context. /// public AssemblyCatalog(Assembly assembly) : this(assembly, (ICompositionElement)null) { } internal AssemblyCatalog(Assembly assembly, ICompositionElement definitionOrigin) { Requires.NotNull(assembly, "assembly"); #if !SILVERLIGHT if (assembly.ReflectionOnly) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.Argument_AssemblyReflectionOnly, "assembly"), "assembly"); } #endif this._assembly = assembly; this._definitionOrigin = definitionOrigin ?? this; } /// /// Gets the part definitions of the assembly catalog. /// /// /// A of objects of the /// . /// /// /// The has been disposed of. /// public override IQueryable Parts { get { return this.InnerCatalog.Parts; } } /// /// Returns the export definitions that match the constraint defined by the specified definition. /// /// /// The that defines the conditions of the /// objects to return. /// /// /// An of containing the /// objects and their associated /// for objects that match the constraint defined /// by . /// /// /// is . /// /// /// The has been disposed of. /// /// /// /// Overriders of this property should never return , if no /// match the conditions defined by /// , return an empty . /// /// public override IEnumerable> GetExports(ImportDefinition definition) { return this.InnerCatalog.GetExports(definition); } private TypeCatalog InnerCatalog { get { this.ThrowIfDisposed(); if (this._innerCatalog == null) { lock (this._thisLock) { if (this._innerCatalog == null) { var catalog = new TypeCatalog(this._assembly.GetTypes(), _definitionOrigin); this._innerCatalog = catalog; } } } return this._innerCatalog; } } /// /// Gets the assembly containing the attributed types contained within the assembly /// catalog. /// /// /// The containing the attributed objects /// contained within the . /// public Assembly Assembly { get { return this._assembly; } } /// /// Gets the display name of the assembly catalog. /// /// /// A containing a human-readable display name of the . /// string ICompositionElement.DisplayName { get { return this.GetDisplayName(); } } /// /// Gets the composition element from which the assembly catalog originated. /// /// /// This property always returns . /// ICompositionElement ICompositionElement.Origin { get { return null; } } /// /// Returns a string representation of the assembly catalog. /// /// /// A containing the string representation of the . /// public override string ToString() { return this.GetDisplayName(); } protected override void Dispose(bool disposing) { if (Interlocked.CompareExchange(ref this._isDisposed, 1, 0) == 0) { try { if (disposing) { if (this._innerCatalog != null) { this._innerCatalog.Dispose(); } } } finally { base.Dispose(disposing); } } } private void ThrowIfDisposed() { if (this._isDisposed == 1) { throw ExceptionBuilder.CreateObjectDisposed(this); } } private string GetDisplayName() { return string.Format(CultureInfo.CurrentCulture, "{0} (Assembly=\"{1}\")", // NOLOC GetType().Name, this.Assembly.FullName); } #if !SILVERLIGHT private static Assembly LoadAssembly(string codeBase) { Requires.NotNullOrEmpty(codeBase, "codeBase"); AssemblyName assemblyName; try { assemblyName = AssemblyName.GetAssemblyName(codeBase); } catch (ArgumentException) { assemblyName = new AssemblyName(); assemblyName.CodeBase = codeBase; } return Assembly.Load(assemblyName); } #endif } }