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