// -----------------------------------------------------------------------
// 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);
}
}
}