1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.Diagnostics.CodeAnalysis;
\r
6 using System.Globalization;
\r
7 using System.Linq.Expressions;
\r
8 using Microsoft.Internal;
\r
10 namespace System.ComponentModel.Composition.Primitives
\r
13 /// Represents an import required by a <see cref="ComposablePart"/> object.
\r
15 public class ImportDefinition
\r
17 internal static readonly string EmptyContractName = string.Empty;
\r
18 private readonly Expression<Func<ExportDefinition, bool>> _constraint;
\r
19 private readonly ImportCardinality _cardinality = ImportCardinality.ExactlyOne;
\r
20 private readonly string _contractName = EmptyContractName;
\r
21 private readonly bool _isRecomposable;
\r
22 private readonly bool _isPrerequisite = true;
\r
23 private Func<ExportDefinition, bool> _compiledConstraint;
\r
26 /// Initializes a new instance of the <see cref="ImportDefinition"/> class.
\r
29 /// <note type="inheritinfo">
\r
30 /// Derived types calling this constructor must override the <see cref="Constraint"/>
\r
31 /// property, and optionally, the <see cref="Cardinality"/>, <see cref="IsPrerequisite"/>
\r
32 /// and <see cref="IsRecomposable"/>
\r
36 protected ImportDefinition()
\r
41 /// Initializes a new instance of the <see cref="ImportDefinition"/> class
\r
42 /// with the specified constraint, cardinality, value indicating if the import
\r
43 /// definition is recomposable and a value indicating if the import definition
\r
44 /// is a prerequisite.
\r
46 /// <param name="constraint">
\r
47 /// A <see cref="Expression{TDelegate}"/> containing a <see cref="Func{T, TResult}"/>
\r
48 /// that defines the conditions that must be matched for the <see cref="ImportDefinition"/>
\r
49 /// to be satisfied by an <see cref="Export"/>.
\r
51 /// <param name="contractName">
\r
52 /// The contract name of the export that this import is interested in. The contract name
\r
53 /// property is used as guidance and not automatically enforced in the constraint. If
\r
54 /// the contract name is a required in the constraint then it should be added to the constraint
\r
55 /// by the caller of this constructor.
\r
57 /// <param name="cardinality">
\r
58 /// One of the <see cref="ImportCardinality"/> values indicating the
\r
59 /// cardinality of the <see cref="Export"/> objects required by the
\r
60 /// <see cref="ImportDefinition"/>.
\r
62 /// <param name="isRecomposable">
\r
63 /// <see langword="true"/> if the <see cref="ImportDefinition"/> can be satisfied
\r
64 /// multiple times throughout the lifetime of a <see cref="ComposablePart"/>, otherwise,
\r
65 /// <see langword="false"/>.
\r
67 /// <param name="isPrerequisite">
\r
68 /// <see langword="true"/> if the <see cref="ImportDefinition"/> is required to be
\r
69 /// satisfied before a <see cref="ComposablePart"/> can start producing exported
\r
70 /// objects; otherwise, <see langword="false"/>.
\r
72 /// <exception cref="ArgumentNullException">
\r
73 /// <paramref name="constraint"/> is <see langword="null"/>.
\r
75 /// <exception cref="ArgumentException">
\r
76 /// <paramref name="cardinality"/> is not one of the <see cref="ImportCardinality"/>
\r
79 [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
\r
80 public ImportDefinition(Expression<Func<ExportDefinition, bool>> constraint, string contractName, ImportCardinality cardinality, bool isRecomposable, bool isPrerequisite)
\r
81 : this(contractName, cardinality, isRecomposable, isPrerequisite)
\r
83 Requires.NotNull(constraint, "constraint");
\r
85 this._constraint = constraint;
\r
88 internal ImportDefinition(string contractName, ImportCardinality cardinality, bool isRecomposable, bool isPrerequisite)
\r
91 (cardinality != ImportCardinality.ExactlyOne) &&
\r
92 (cardinality != ImportCardinality.ZeroOrMore) &&
\r
93 (cardinality != ImportCardinality.ZeroOrOne)
\r
96 throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.ArgumentOutOfRange_InvalidEnum, "cardinality", cardinality, typeof(ImportCardinality).Name), "cardinality");
\r
99 this._contractName = contractName ?? EmptyContractName;
\r
100 this._cardinality = cardinality;
\r
101 this._isRecomposable = isRecomposable;
\r
102 this._isPrerequisite = isPrerequisite;
\r
106 /// Gets the contract name of the export required by the import definition.
\r
109 /// A <see cref="String"/> containing the contract name of the <see cref="Export"/>
\r
110 /// required by the <see cref="ContractBasedImportDefinition"/>. This property should
\r
111 /// return <see cref="String.Empty"/> for imports that do not require a specific
\r
114 public virtual string ContractName
\r
116 get { return this._contractName; }
\r
120 /// Gets the cardinality of the exports required by the import definition.
\r
123 /// One of the <see cref="ImportCardinality"/> values indicating the
\r
124 /// cardinality of the <see cref="Export"/> objects required by the
\r
125 /// <see cref="ImportDefinition"/>. The default is
\r
126 /// <see cref="ImportCardinality.ExactlyOne"/>
\r
128 public virtual ImportCardinality Cardinality
\r
130 get { return this._cardinality; }
\r
134 /// Gets an expression that defines conditions that must be matched for the import
\r
135 /// described by the import definition to be satisfied.
\r
138 /// A <see cref="Expression{TDelegate}"/> containing a <see cref="Func{T, TResult}"/>
\r
139 /// that defines the conditions that must be matched for the
\r
140 /// <see cref="ImportDefinition"/> to be satisfied by an <see cref="Export"/>.
\r
142 /// <exception cref="NotImplementedException">
\r
143 /// The property was not overridden by a derived class.
\r
146 /// <note type="inheritinfo">
\r
147 /// Overriders of this property should never return <see langword="null"/>.
\r
150 [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
\r
151 public virtual Expression<Func<ExportDefinition, bool>> Constraint
\r
155 if (this._constraint != null)
\r
157 return this._constraint;
\r
160 throw ExceptionBuilder.CreateNotOverriddenByDerived("Constraint");
\r
165 /// Gets a value indicating whether the import definition is required to be
\r
166 /// satisfied before a part can start producing exported values.
\r
169 /// <see langword="true"/> if the <see cref="ImportDefinition"/> is required to be
\r
170 /// satisfied before a <see cref="ComposablePart"/> can start producing exported
\r
171 /// objects; otherwise, <see langword="false"/>. The default is <see langword="true"/>.
\r
173 public virtual bool IsPrerequisite
\r
175 get { return this._isPrerequisite; }
\r
179 /// Gets a value indicating whether the import definition can be satisfied multiple times.
\r
182 /// <see langword="true"/> if the <see cref="ImportDefinition"/> can be satisfied
\r
183 /// multiple times throughout the lifetime of a <see cref="ComposablePart"/>, otherwise,
\r
184 /// <see langword="false"/>. The default is <see langword="false"/>.
\r
186 public virtual bool IsRecomposable
\r
188 get { return this._isRecomposable; }
\r
192 /// Executes of the constraint provided by the <see cref="Constraint"/> property
\r
193 /// against a given <see cref="ExportDefinition"/> to determine if this
\r
194 /// <see cref="ImportDefinition"/> can be satisfied by the given <see cref="Export"/>.
\r
196 /// <param name="exportDefinition">
\r
197 /// A definition for a <see cref="Export"/> used to determine if it satisfies the
\r
198 /// requirements for this <see cref="ImportDefinition"/>.
\r
201 /// <see langword="True"/> if the <see cref="Export"/> satisfies the requirements for
\r
202 /// this <see cref="ImportDefinition"/>, otherwise returns <see langword="False"/>.
\r
205 /// <note type="inheritinfo">
\r
206 /// Overrides of this method can provide a more optimized execution of the
\r
207 /// <see cref="Constraint"/> property but the result should remain consistent.
\r
210 /// <exception cref="ArgumentNullException">
\r
211 /// <paramref name="exportDefinition"/> is <see langword="null"/>.
\r
213 public virtual bool IsConstraintSatisfiedBy(ExportDefinition exportDefinition)
\r
215 Requires.NotNull(exportDefinition, "exportDefinition");
\r
217 if (this._compiledConstraint == null)
\r
219 this._compiledConstraint = this.Constraint.Compile();
\r
222 return this._compiledConstraint.Invoke(exportDefinition);
\r
226 /// Returns a string representation of the import definition.
\r
229 /// A <see cref="String"/> containing the value of the <see cref="Constraint"/> property.
\r
231 public override string ToString()
\r
233 return this.Constraint.Body.ToString();
\r