1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.Collections.Generic;
\r
6 using System.ComponentModel.Composition.Primitives;
\r
7 using System.Globalization;
\r
9 using Microsoft.Internal;
\r
11 namespace System.ComponentModel.Composition.Hosting
\r
14 /// Defines the <see langword="abstract"/> base class for export providers, which provide
\r
15 /// methods for retrieving <see cref="Export"/> objects.
\r
17 public abstract partial class ExportProvider
\r
20 /// Initializes a new instance of the <see cref="ExportProvider"/> class.
\r
22 protected ExportProvider()
\r
27 /// Occurs when the exports in the <see cref="ExportProvider"/> have changed.
\r
29 public event EventHandler<ExportsChangeEventArgs> ExportsChanged;
\r
32 /// Occurs when the exports in the <see cref="ExportProvider"/> are changing.
\r
34 public event EventHandler<ExportsChangeEventArgs> ExportsChanging;
\r
37 /// Returns all exports that match the conditions of the specified import.
\r
39 /// <param name="definition">
\r
40 /// The <see cref="ImportDefinition"/> that defines the conditions of the
\r
41 /// <see cref="Export"/> objects to get.
\r
44 /// An <see cref="IEnumerable{T}"/> of <see cref="Export"/> objects that match
\r
45 /// the conditions defined by <see cref="ImportDefinition"/>, if found; otherwise, an
\r
46 /// empty <see cref="IEnumerable{T}"/>.
\r
48 /// <exception cref="ArgumentNullException">
\r
49 /// <paramref name="definition"/> is <see langword="null"/>.
\r
51 /// <exception cref="ImportCardinalityMismatchException">
\r
53 /// <see cref="ImportDefinition.Cardinality"/> is <see cref="ImportCardinality.ExactlyOne"/> and
\r
54 /// there are zero <see cref="Export"/> objects that match the conditions of the specified
\r
55 /// <see cref="ImportDefinition"/>.
\r
59 /// <see cref="ImportDefinition.Cardinality"/> is <see cref="ImportCardinality.ZeroOrOne"/> or
\r
60 /// <see cref="ImportCardinality.ExactlyOne"/> and there are more than one <see cref="Export"/>
\r
61 /// objects that match the conditions of the specified <see cref="ImportDefinition"/>.
\r
64 public IEnumerable<Export> GetExports(ImportDefinition definition)
\r
66 return GetExports(definition, null);
\r
70 /// Returns all exports that match the conditions of the specified import.
\r
72 /// <param name="definition">
\r
73 /// The <see cref="ImportDefinition"/> that defines the conditions of the
\r
74 /// <see cref="Export"/> objects to get.
\r
77 /// An <see cref="IEnumerable{T}"/> of <see cref="Export"/> objects that match
\r
78 /// the conditions defined by <see cref="ImportDefinition"/>, if found; otherwise, an
\r
79 /// empty <see cref="IEnumerable{T}"/>.
\r
81 /// <exception cref="ArgumentNullException">
\r
82 /// <paramref name="definition"/> is <see langword="null"/>.
\r
84 /// <exception cref="ImportCardinalityMismatchException">
\r
86 /// <see cref="ImportDefinition.Cardinality"/> is <see cref="ImportCardinality.ExactlyOne"/> and
\r
87 /// there are zero <see cref="Export"/> objects that match the conditions of the specified
\r
88 /// <see cref="ImportDefinition"/>.
\r
92 /// <see cref="ImportDefinition.Cardinality"/> is <see cref="ImportCardinality.ZeroOrOne"/> or
\r
93 /// <see cref="ImportCardinality.ExactlyOne"/> and there are more than one <see cref="Export"/>
\r
94 /// objects that match the conditions of the specified <see cref="ImportDefinition"/>.
\r
97 public IEnumerable<Export> GetExports(ImportDefinition definition, AtomicComposition atomicComposition)
\r
99 Requires.NotNull(definition, "definition");
\r
101 IEnumerable<Export> exports;
\r
102 ExportCardinalityCheckResult result = this.TryGetExportsCore(definition, atomicComposition, out exports);
\r
105 case ExportCardinalityCheckResult.Match:
\r
107 case ExportCardinalityCheckResult.NoExports:
\r
108 throw new ImportCardinalityMismatchException(string.Format(CultureInfo.CurrentCulture, Strings.CardinalityMismatch_NoExports, definition.Constraint.Body.ToString()));
\r
110 Assumes.IsTrue(result == ExportCardinalityCheckResult.TooManyExports);
\r
111 throw new ImportCardinalityMismatchException(string.Format(CultureInfo.CurrentCulture, Strings.CardinalityMismatch_TooManyExports, definition.Constraint.Body.ToString()));
\r
116 /// Returns all exports that match the conditions of the specified import.
\r
118 /// <param name="definition">
\r
119 /// The <see cref="ImportDefinition"/> that defines the conditions of the
\r
120 /// <see cref="Export"/> objects to get.
\r
122 /// <param name="exports">
\r
123 /// When this method returns, contains an <see cref="IEnumerable{T}"/> of <see cref="Export"/>
\r
124 /// objects that match the conditions defined by <see cref="ImportDefinition"/>, if found;
\r
125 /// otherwise, an empty <see cref="IEnumerable{T}"/>.
\r
128 /// <see langword="true"/> if <see cref="ImportDefinition.Cardinality"/> is
\r
129 /// <see cref="ImportCardinality.ZeroOrOne"/> or <see cref="ImportCardinality.ZeroOrMore"/> and
\r
130 /// there are zero <see cref="Export"/> objects that match the conditions of the specified
\r
131 /// <see cref="ImportDefinition"/>. <see langword="true"/> if
\r
132 /// <see cref="ImportDefinition.Cardinality"/> is <see cref="ImportCardinality.ZeroOrOne"/> or
\r
133 /// <see cref="ImportCardinality.ExactlyOne"/> and there is exactly one <see cref="Export"/>
\r
134 /// that matches the conditions of the specified <see cref="ImportDefinition"/>; otherwise,
\r
135 /// <see langword="false"/>.
\r
137 /// <exception cref="ArgumentNullException">
\r
138 /// <paramref name="definition"/> is <see langword="null"/>.
\r
140 public bool TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, out IEnumerable<Export> exports)
\r
142 Requires.NotNull(definition, "definition");
\r
145 ExportCardinalityCheckResult result = this.TryGetExportsCore(definition, atomicComposition, out exports);
\r
146 return (result == ExportCardinalityCheckResult.Match);
\r
150 /// Returns all exports that match the constraint defined by the specified definition.
\r
152 /// <param name="definition">
\r
153 /// The <see cref="ImportDefinition"/> that defines the conditions of the
\r
154 /// <see cref="Export"/> objects to return.
\r
157 /// An <see cref="IEnumerable{T}"/> of <see cref="Export"/> objects that match
\r
158 /// the conditions defined by <see cref="ImportDefinition"/>, if found; otherwise, an
\r
159 /// empty <see cref="IEnumerable{T}"/>.
\r
162 /// <note type="inheritinfo">
\r
163 /// Overriders of this method should not treat cardinality-related mismatches
\r
164 /// as errors, and should not throw exceptions in those cases. For instance,
\r
165 /// if <see cref="ImportDefinition.Cardinality"/> is <see cref="ImportCardinality.ExactlyOne"/>
\r
166 /// and there are zero <see cref="Export"/> objects that match the conditions of the
\r
167 /// specified <see cref="ImportDefinition"/>, an <see cref="IEnumerable{T}"/> should be returned.
\r
170 protected abstract IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition);
\r
173 /// Raises the <see cref="ExportsChanged"/> event.
\r
175 /// <param name="e">
\r
176 /// An <see cref="ExportsChangeEventArgs"/> containing the data for the event.
\r
178 protected virtual void OnExportsChanged(ExportsChangeEventArgs e)
\r
180 EventHandler<ExportsChangeEventArgs> changedEvent = this.ExportsChanged;
\r
181 if (changedEvent != null)
\r
183 CompositionResult result = CompositionServices.TryFire(changedEvent, this, e);
\r
184 result.ThrowOnErrors(e.AtomicComposition);
\r
189 /// Raises the <see cref="ExportsChanging"/> event.
\r
191 /// <param name="e">
\r
192 /// An <see cref="ExportsChangeEventArgs"/> containing the data for the event.
\r
194 protected virtual void OnExportsChanging(ExportsChangeEventArgs e)
\r
196 EventHandler<ExportsChangeEventArgs> changingEvent = this.ExportsChanging;
\r
197 if (changingEvent != null)
\r
199 CompositionResult result = CompositionServices.TryFire(changingEvent, this, e);
\r
200 result.ThrowOnErrors(e.AtomicComposition);
\r
204 private ExportCardinalityCheckResult TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, out IEnumerable<Export> exports)
\r
206 Assumes.NotNull(definition);
\r
208 exports = this.GetExportsCore(definition, atomicComposition);
\r
210 if (exports == null)
\r
212 exports = Enumerable.Empty<Export>();
\r
215 var checkResult = ExportServices.CheckCardinality(definition, exports);
\r
217 // Export providers treat >1 match as zero for cardinality 0-1 imports
\r
218 // If this policy is moved we need to revisit the assumption that the
\r
219 // ImportEngine made during previewing the only required imports to
\r
220 // now also preview optional imports.
\r
221 if (checkResult == ExportCardinalityCheckResult.TooManyExports &&
\r
222 definition.Cardinality == ImportCardinality.ZeroOrOne)
\r
224 checkResult = ExportCardinalityCheckResult.Match;
\r
225 exports = Enumerable.Empty<Export>();
\r
228 return checkResult;
\r