// ----------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // ----------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel.Composition.Primitives; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Collections.ObjectModel; using Microsoft.Internal; using Microsoft.Internal.Collections; namespace System.ComponentModel.Composition.Hosting { public abstract partial class ExportProvider { /// /// Returns the export with the contract name derived from the specified type parameter, /// throwing an exception if there is not exactly one matching export. /// /// /// The type of the object to return. The contract name is also /// derived from this type parameter. /// /// /// The object with the contract name derived from /// . /// /// /// /// The returned object is an instance of /// underneath, where /// TMetadataView /// is and where TKey /// is and TValue is . /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// /// There are zero objects with the contract name derived /// from in the . /// /// -or- /// /// There are more than one objects with the contract name /// derived from in the . /// /// /// /// The has been disposed of. /// public Lazy GetExport() { return this.GetExport((string)null); } /// /// Returns the export with the specified contract name, throwing an exception if there /// is not exactly one matching export. /// /// /// The type of the object to return. /// /// /// A containing the contract name of the /// object to return; or or an empty string ("") to use the /// default contract name. /// /// /// The object with the specified contract name. /// /// /// /// The returned object is an instance of /// underneath, where /// TMetadataView /// is and where TKey /// is and TValue is . /// /// /// The contract name is the result of calling /// on . /// /// /// The default contract name is compared using a case-sensitive, non-linguistic /// comparison using . /// /// /// /// /// There are zero objects with the specified contract name /// in the . /// /// -or- /// /// There are more than one objects with the specified contract /// name in the . /// /// /// /// The has been disposed of. /// public Lazy GetExport(string contractName) { return this.GetExportCore(contractName); } /// /// Returns the export with the contract name derived from the specified type parameter, /// throwing an exception if there is not exactly one matching export. /// /// /// The type of the object to return. The /// contract name is also derived from this type parameter. /// /// /// The type of the metadata view of the object /// to return. /// /// /// The object with the contract name derived /// from . /// /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// /// There are zero objects with the contract /// name derived from in the /// . /// /// -or- /// /// There are more than one objects with the /// contract name derived from in the /// . /// /// /// /// is not a valid metadata view type. /// /// /// The has been disposed of. /// public Lazy GetExport() { return this.GetExport((string)null); } /// /// Returns the export with the specified contract name, throwing an exception if there /// is not exactly one matching export. /// /// /// The type of the object to return. /// /// /// The type of the metadata view of the object /// to return. /// /// /// A containing the contract name of the /// object to return; or /// or an empty string ("") to use the default contract name. /// /// /// The object with the specified contract name. /// /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// /// There are zero objects with the /// specified contract name in the . /// /// -or- /// /// There are more than one objects with the /// specified contract name in the . /// /// /// /// is not a valid metadata view type. /// /// /// The has been disposed of. /// public Lazy GetExport(string contractName) { return this.GetExportCore(contractName); } /// /// Returns the exports with the specified contract name. /// /// /// The of the objects to return. /// /// /// The of the metadata view of the objects to /// return. /// /// /// A containing the contract name of the /// object to return; or /// or an empty string ("") to use the default contract name. /// /// /// An containing the objects /// with the specified contract name, if found; otherwise, an empty /// . /// /// /// /// The returned objects are instances of /// underneath, where T /// is and TMetadataView is /// . /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// is . /// /// /// is not a valid metadata view type. /// /// /// The has been disposed of. /// [SuppressMessage("Microsoft.Design", "CA1006")] public IEnumerable> GetExports(Type type, Type metadataViewType, string contractName) { IEnumerable exports = this.GetExportsCore(type, metadataViewType, contractName, ImportCardinality.ZeroOrMore); Collection> result = new Collection>(); Func> typedExportFactory = ExportServices.CreateSemiStronglyTypedLazyFactory(type, metadataViewType); foreach (Export export in exports) { result.Add(typedExportFactory.Invoke(export)); } return result; } /// /// Returns the exports with the contract name derived from the specified type parameter. /// /// /// The type of the objects to return. The contract name is also /// derived from this type parameter. /// /// /// An containing the objects /// with the contract name derived from , if found; otherwise, /// an empty . /// /// /// /// The returned objects are instances of /// underneath, where /// TMetadataView /// is and where TKey /// is and TValue is . /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// The has been disposed of. /// [SuppressMessage("Microsoft.Design", "CA1006")] public IEnumerable> GetExports() { return this.GetExports((string)null); } /// /// Returns the exports with the specified contract name. /// /// /// The type of the objects to return. /// /// /// A containing the contract name of the /// objects to return; or or an empty string ("") to use the /// default contract name. /// /// /// An containing the objects /// with the specified contract name, if found; otherwise, an empty /// . /// /// /// /// The returned objects are instances of /// underneath, where /// TMetadataView /// is and where TKey /// is and TValue is . /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// The has been disposed of. /// [SuppressMessage("Microsoft.Design", "CA1006")] public IEnumerable> GetExports(string contractName) { return this.GetExportsCore(contractName); } /// /// Returns the exports with the contract name derived from the specified type parameter. /// /// /// The type of the objects to return. The /// contract name is also derived from this type parameter. /// /// /// The type of the metadata view of the objects /// to return. /// /// /// An containing the /// objects with the contract name derived from /// , if found; otherwise, an empty /// . /// /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// is not a valid metadata view type. /// /// /// The has been disposed of. /// [SuppressMessage("Microsoft.Design", "CA1006")] public IEnumerable> GetExports() { return this.GetExports((string)null); } /// /// Returns the exports with the specified contract name. /// /// /// The type of the objects to return. The /// contract name is also derived from this type parameter. /// /// /// The type of the metadata view of the objects /// to return. /// /// /// A containing the contract name of the /// objects to return; or /// or an empty string ("") to use the default contract name. /// /// /// An containing the /// objects with the specified contract name if /// found; otherwise, an empty . /// /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// is not a valid metadata view type. /// /// /// The has been disposed of. /// [SuppressMessage("Microsoft.Design", "CA1006")] public IEnumerable> GetExports(string contractName) { return this.GetExportsCore(contractName); } /// /// Returns the exported value with the contract name derived from the specified type /// parameter, throwing an exception if there is not exactly one matching exported value. /// /// /// The type of the exported value to return. The contract name is also /// derived from this type parameter. /// /// /// The exported with the contract name derived from /// . /// /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// The underlying exported value cannot be cast to . /// /// /// /// There are zero exported values with the contract name derived from /// in the . /// /// -or- /// /// There are more than one exported values with the contract name derived from /// in the . /// /// /// /// The has been disposed of. /// /// /// An error occurred during composition. will /// contain a collection of errors that occurred. /// public T GetExportedValue() { return this.GetExportedValue((string)null); } /// /// Returns the exported value with the specified contract name, throwing an exception /// if there is not exactly one matching exported value. /// /// /// The type of the exported value to return. /// /// /// A containing the contract name of the exported value to return, /// or or an empty string ("") to use the default contract name. /// /// /// The exported with the specified contract name. /// /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// The underlying exported value cannot be cast to . /// /// /// /// There are zero exported values with the specified contract name in the /// . /// /// -or- /// /// There are more than one exported values with the specified contract name in the /// . /// /// /// /// The has been disposed of. /// /// /// An error occurred during composition. will /// contain a collection of errors that occurred. /// public T GetExportedValue(string contractName) { return this.GetExportedValueCore(contractName, ImportCardinality.ExactlyOne); } /// /// Returns the exported value with the contract name derived from the specified type /// parameter, throwing an exception if there is more than one matching exported value. /// /// /// The type of the exported value to return. The contract name is also /// derived from this type parameter. /// /// /// The exported with the contract name derived from /// , if found; otherwise, the default value for /// . /// /// /// /// If the exported value is not found, then this method returns the appropriate /// default value for ; for example, 0 (zero) for integer /// types, for Boolean types, and /// for reference types. /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// The underlying exported value cannot be cast to . /// /// /// /// There are more than one exported values with the contract name derived from /// in the . /// /// /// /// The has been disposed of. /// /// /// An error occurred during composition. will /// contain a collection of errors that occurred. /// public T GetExportedValueOrDefault() { return this.GetExportedValueOrDefault((string)null); } /// /// Returns the exported value with the specified contract name, throwing an exception /// if there is more than one matching exported value. /// /// /// The type of the exported value to return. /// /// /// A containing the contract name of the exported value to return, /// or or an empty string ("") to use the default contract name. /// /// /// The exported with the specified contract name, if found; /// otherwise, the default value for . /// /// /// /// If the exported value is not found, then this method returns the appropriate /// default value for ; for example, 0 (zero) for integer /// types, for Boolean types, and /// for reference types. /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// The underlying exported value cannot be cast to . /// /// /// There are more than one exported values with the specified contract name in the /// . /// /// /// The has been disposed of. /// /// /// An error occurred during composition. will /// contain a collection of errors that occurred. /// public T GetExportedValueOrDefault(string contractName) { return this.GetExportedValueCore(contractName, ImportCardinality.ZeroOrOne); } /// /// Returns the exported values with the contract name derived from the specified type /// parameter. /// /// /// The type of the exported value to return. The contract name is also /// derived from this type parameter. /// /// /// An containing the exported values with the contract name /// derived from the specified type parameter, if found; otherwise, an empty /// . /// /// /// /// The contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// One or more of the underlying exported values cannot be cast to /// . /// /// /// The has been disposed of. /// /// /// An error occurred during composition. will /// contain a collection of errors that occurred. /// public IEnumerable GetExportedValues() { return this.GetExportedValues((string)null); } /// /// Returns the exported values with the specified contract name. /// /// /// The type of the exported value to return. /// /// /// A containing the contract name of the exported values to /// return; or or an empty string ("") to use the default /// contract name. /// /// /// An containing the exported values with the specified /// contract name, if found; otherwise, an empty . /// /// /// /// The default contract name is the result of calling /// on . /// /// /// The contract name is compared using a case-sensitive, non-linguistic comparison /// using . /// /// /// /// One or more of the underlying exported values cannot be cast to /// . /// /// /// The has been disposed of. /// /// /// An error occurred during composition. will /// contain a collection of errors that occurred. /// public IEnumerable GetExportedValues(string contractName) { return this.GetExportedValuesCore(contractName); } private IEnumerable GetExportedValuesCore(string contractName) { IEnumerable exports = this.GetExportsCore(typeof(T), (Type)null, contractName, ImportCardinality.ZeroOrMore); Collection result = new Collection(); foreach (Export export in exports) { result.Add(ExportServices.GetCastedExportedValue(export)); } return result; } private T GetExportedValueCore(string contractName, ImportCardinality cardinality) { Assumes.IsTrue(cardinality.IsAtMostOne()); Export export = this.GetExportsCore(typeof(T), (Type)null, contractName, cardinality).SingleOrDefault(); return (export != null) ? ExportServices.GetCastedExportedValue(export) : default(T); } private IEnumerable> GetExportsCore(string contractName) { IEnumerable exports = this.GetExportsCore(typeof(T), (Type)null, contractName, ImportCardinality.ZeroOrMore); Collection> result = new Collection>(); foreach (Export export in exports) { result.Add(ExportServices.CreateStronglyTypedLazyOfT(export)); } return result; } private IEnumerable> GetExportsCore(string contractName) { IEnumerable exports = this.GetExportsCore(typeof(T), typeof(TMetadataView), contractName, ImportCardinality.ZeroOrMore); Collection> result = new Collection>(); foreach (Export export in exports) { result.Add(ExportServices.CreateStronglyTypedLazyOfTM(export)); } return result; } private Lazy GetExportCore(string contractName) { Export export = this.GetExportsCore(typeof(T), typeof(TMetadataView), contractName, ImportCardinality.ExactlyOne).SingleOrDefault(); return (export != null) ? ExportServices.CreateStronglyTypedLazyOfTM(export) : null; } private Lazy GetExportCore(string contractName) { Export export = this.GetExportsCore(typeof(T), null, contractName, ImportCardinality.ExactlyOne).SingleOrDefault(); return (export != null) ? ExportServices.CreateStronglyTypedLazyOfT(export) : null; } private IEnumerable GetExportsCore(Type type, Type metadataViewType, string contractName, ImportCardinality cardinality) { // Only 'type' cannot be null - the other parameters have sensible defaults. Requires.NotNull(type, "type"); if (string.IsNullOrEmpty(contractName)) { contractName = AttributedModelServices.GetContractName(type); } if (metadataViewType == null) { metadataViewType = ExportServices.DefaultMetadataViewType; } if (!MetadataViewProvider.IsViewTypeValid(metadataViewType)) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings.InvalidMetadataView, metadataViewType.Name)); } ImportDefinition importDefinition = BuildImportDefinition(type, metadataViewType, contractName, cardinality); return this.GetExports(importDefinition, null); } private static ImportDefinition BuildImportDefinition(Type type, Type metadataViewType, string contractName, ImportCardinality cardinality) { Assumes.NotNull(type, metadataViewType, contractName); IEnumerable> requiredMetadata = CompositionServices.GetRequiredMetadata(metadataViewType); string requiredTypeIdentity = null; if (type != typeof(object)) { requiredTypeIdentity = AttributedModelServices.GetTypeIdentity(type); } return new ContractBasedImportDefinition(contractName, requiredTypeIdentity, requiredMetadata, cardinality, false, true, CreationPolicy.Any); } } }