1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
4 using System.Collections.Generic;
5 using System.Collections.ObjectModel;
6 using System.ComponentModel.Composition.Primitives;
7 using System.Diagnostics.CodeAnalysis;
8 using System.Globalization;
10 using Microsoft.Internal;
12 namespace System.ComponentModel.Composition.Hosting
14 public abstract partial class ExportProvider
17 /// Returns the export with the contract name derived from the specified type parameter,
18 /// throwing an exception if there is not exactly one matching export.
20 /// <typeparam name="T">
21 /// The type of the <see cref="Lazy{T}"/> object to return. The contract name is also
22 /// derived from this type parameter.
25 /// The <see cref="Lazy{T}"/> object with the contract name derived from
26 /// <typeparamref name="T"/>.
30 /// The returned <see cref="Lazy{T}"/> object is an instance of
31 /// <see cref="Lazy{T, TMetadataView}"/> underneath, where
32 /// <c>TMetadataView</c>
33 /// is <see cref="IDictionary{TKey, TValue}"/> and where <c>TKey</c>
34 /// is <see cref="string"/> and <c>TValue</c> is <see cref="object"/>.
37 /// The contract name is the result of calling
38 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
41 /// The contract name is compared using a case-sensitive, non-linguistic comparison
42 /// using <see cref="StringComparer.Ordinal"/>.
45 /// <exception cref="ImportCardinalityMismatchException">
47 /// There are zero <see cref="Lazy{T}"/> objects with the contract name derived
48 /// from <typeparamref name="T"/> in the <see cref="CompositionContainer"/>.
52 /// There are more than one <see cref="Lazy{T}"/> objects with the contract name
53 /// derived from <typeparamref name="T"/> in the <see cref="CompositionContainer"/>.
56 /// <exception cref="ObjectDisposedException">
57 /// The <see cref="CompositionContainer"/> has been disposed of.
59 public Lazy<T>? GetExport<T>()
61 return GetExport<T>((string?)null);
65 /// Returns the export with the specified contract name, throwing an exception if there
66 /// is not exactly one matching export.
68 /// <typeparam name="T">
69 /// The type of the <see cref="Lazy{T}"/> object to return.
71 /// <param name="contractName">
72 /// A <see cref="string"/> containing the contract name of the <see cref="Lazy{T}"/>
73 /// object to return; or <see langword="null"/> or an empty string ("") to use the
74 /// default contract name.
77 /// The <see cref="Lazy{T}"/> object with the specified contract name.
81 /// The returned <see cref="Lazy{T}"/> object is an instance of
82 /// <see cref="Lazy{T, TMetadataView}"/> underneath, where
83 /// <c>TMetadataView</c>
84 /// is <see cref="IDictionary{TKey, TValue}"/> and where <c>TKey</c>
85 /// is <see cref="string"/> and <c>TValue</c> is <see cref="object"/>.
88 /// The contract name is the result of calling
89 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
92 /// The default contract name is compared using a case-sensitive, non-linguistic
93 /// comparison using <see cref="StringComparer.Ordinal"/>.
96 /// <exception cref="ImportCardinalityMismatchException">
98 /// There are zero <see cref="Lazy{T}"/> objects with the specified contract name
99 /// in the <see cref="CompositionContainer"/>.
103 /// There are more than one <see cref="Lazy{T}"/> objects with the specified contract
104 /// name in the <see cref="CompositionContainer"/>.
107 /// <exception cref="ObjectDisposedException">
108 /// The <see cref="CompositionContainer"/> has been disposed of.
110 public Lazy<T>? GetExport<T>(string? contractName)
112 return GetExportCore<T>(contractName);
116 /// Returns the export with the contract name derived from the specified type parameter,
117 /// throwing an exception if there is not exactly one matching export.
119 /// <typeparam name="T">
120 /// The type of the <see cref="Lazy{T, TMetadataView}"/> object to return. The
121 /// contract name is also derived from this type parameter.
123 /// <typeparam name="TMetadataView">
124 /// The type of the metadata view of the <see cref="Lazy{T, TMetadataView}"/> object
128 /// The <see cref="Lazy{T, TMetadataView}"/> object with the contract name derived
129 /// from <typeparamref name="T"/>.
133 /// The contract name is the result of calling
134 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
137 /// The contract name is compared using a case-sensitive, non-linguistic comparison
138 /// using <see cref="StringComparer.Ordinal"/>.
141 /// <exception cref="ImportCardinalityMismatchException">
143 /// There are zero <see cref="Lazy{T, TMetadataView}"/> objects with the contract
144 /// name derived from <typeparamref name="T"/> in the
145 /// <see cref="CompositionContainer"/>.
149 /// There are more than one <see cref="Lazy{T, TMetadataView}"/> objects with the
150 /// contract name derived from <typeparamref name="T"/> in the
151 /// <see cref="CompositionContainer"/>.
154 /// <exception cref="InvalidOperationException">
155 /// <typeparamref name="TMetadataView"/> is not a valid metadata view type.
157 /// <exception cref="ObjectDisposedException">
158 /// The <see cref="CompositionContainer"/> has been disposed of.
160 public Lazy<T, TMetadataView>? GetExport<T, TMetadataView>()
162 return GetExport<T, TMetadataView>((string?)null);
166 /// Returns the export with the specified contract name, throwing an exception if there
167 /// is not exactly one matching export.
169 /// <typeparam name="T">
170 /// The type of the <see cref="Lazy{T, TMetadataView}"/> object to return.
172 /// <typeparam name="TMetadataView">
173 /// The type of the metadata view of the <see cref="Lazy{T, TMetadataView}"/> object
176 /// <param name="contractName">
177 /// A <see cref="string"/> containing the contract name of the
178 /// <see cref="Lazy{T, TMetadataView}"/> object to return; or <see langword="null"/>
179 /// or an empty string ("") to use the default contract name.
182 /// The <see cref="Lazy{T, TMetadataView}"/> object with the specified contract name.
186 /// The default contract name is the result of calling
187 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
190 /// The contract name is compared using a case-sensitive, non-linguistic comparison
191 /// using <see cref="StringComparer.Ordinal"/>.
194 /// <exception cref="ImportCardinalityMismatchException">
196 /// There are zero <see cref="Lazy{T, TMetadataView}"/> objects with the
197 /// specified contract name in the <see cref="CompositionContainer"/>.
201 /// There are more than one <see cref="Lazy{T, TMetadataView}"/> objects with the
202 /// specified contract name in the <see cref="CompositionContainer"/>.
205 /// <exception cref="InvalidOperationException">
206 /// <typeparamref name="TMetadataView"/> is not a valid metadata view type.
208 /// <exception cref="ObjectDisposedException">
209 /// The <see cref="CompositionContainer"/> has been disposed of.
211 public Lazy<T, TMetadataView>? GetExport<T, TMetadataView>(string? contractName)
213 return GetExportCore<T, TMetadataView>(contractName);
217 /// Returns the exports with the specified contract name.
219 /// <param name="type">
220 /// The <see cref="Type"/> of the <see cref="Export"/> objects to return.
222 /// <param name="metadataViewType">
223 /// The <see cref="Type"/> of the metadata view of the <see cref="Export"/> objects to
226 /// <param name="contractName">
227 /// A <see cref="string"/> containing the contract name of the
228 /// <see cref="Export"/> object to return; or <see langword="null"/>
229 /// or an empty string ("") to use the default contract name.
232 /// An <see cref="IEnumerable{T}"/> containing the <see cref="Lazy{Object, Object}"/> objects
233 /// with the specified contract name, if found; otherwise, an empty
234 /// <see cref="IEnumerable{T}"/>.
238 /// The returned <see cref="Export"/> objects are instances of
239 /// <see cref="Lazy{T, TMetadataView}"/> underneath, where <c>T</c>
240 /// is <paramref name="type"/> and <c>TMetadataView</c> is
241 /// <paramref name="metadataViewType"/>.
244 /// The default contract name is the result of calling
245 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <paramref name="type"/>.
248 /// The contract name is compared using a case-sensitive, non-linguistic comparison
249 /// using <see cref="StringComparer.Ordinal"/>.
252 /// <exception cref="ArgumentNullException">
253 /// <paramref name="type"/> is <see langword="null"/>.
255 /// <exception cref="InvalidOperationException">
256 /// <paramref name="metadataViewType"/> is not a valid metadata view type.
258 /// <exception cref="ObjectDisposedException">
259 /// The <see cref="CompositionContainer"/> has been disposed of.
261 public IEnumerable<Lazy<object, object>> GetExports(Type type, Type? metadataViewType, string? contractName)
263 IEnumerable<Export> exports = GetExportsCore(type, metadataViewType, contractName, ImportCardinality.ZeroOrMore);
264 Collection<Lazy<object, object>> result = new Collection<Lazy<object, object>>();
266 Func<Export, Lazy<object, object>> typedExportFactory = ExportServices.CreateSemiStronglyTypedLazyFactory(type, metadataViewType);
267 foreach (Export export in exports)
269 result.Add(typedExportFactory.Invoke(export));
276 /// Returns the exports with the contract name derived from the specified type parameter.
278 /// <typeparam name="T">
279 /// The type of the <see cref="Lazy{T}"/> objects to return. The contract name is also
280 /// derived from this type parameter.
283 /// An <see cref="IEnumerable{T}"/> containing the <see cref="Lazy{T}"/> objects
284 /// with the contract name derived from <typeparamref name="T"/>, if found; otherwise,
285 /// an empty <see cref="IEnumerable{T}"/>.
289 /// The returned <see cref="Lazy{T}"/> objects are instances of
290 /// <see cref="Lazy{T, TMetadataView}"/> underneath, where
291 /// <c>TMetadataView</c>
292 /// is <see cref="IDictionary{TKey, TValue}"/> and where <c>TKey</c>
293 /// is <see cref="string"/> and <c>TValue</c> is <see cref="object"/>.
296 /// The contract name is the result of calling
297 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
300 /// The contract name is compared using a case-sensitive, non-linguistic comparison
301 /// using <see cref="StringComparer.Ordinal"/>.
304 /// <exception cref="ObjectDisposedException">
305 /// The <see cref="CompositionContainer"/> has been disposed of.
307 public IEnumerable<Lazy<T>> GetExports<T>()
309 return GetExports<T>((string?)null);
313 /// Returns the exports with the specified contract name.
315 /// <typeparam name="T">
316 /// The type of the <see cref="Lazy{T}"/> objects to return.
318 /// <param name="contractName">
319 /// A <see cref="string"/> containing the contract name of the <see cref="Lazy{T}"/>
320 /// objects to return; or <see langword="null"/> or an empty string ("") to use the
321 /// default contract name.
324 /// An <see cref="IEnumerable{T}"/> containing the <see cref="Lazy{T}"/> objects
325 /// with the specified contract name, if found; otherwise, an empty
326 /// <see cref="IEnumerable{T}"/>.
330 /// The returned <see cref="Lazy{T}"/> objects are instances of
331 /// <see cref="Lazy{T, TMetadataView}"/> underneath, where
332 /// <c>TMetadataView</c>
333 /// is <see cref="IDictionary{TKey, TValue}"/> and where <c>TKey</c>
334 /// is <see cref="string"/> and <c>TValue</c> is <see cref="object"/>.
337 /// The default contract name is the result of calling
338 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
341 /// The contract name is compared using a case-sensitive, non-linguistic comparison
342 /// using <see cref="StringComparer.Ordinal"/>.
345 /// <exception cref="ObjectDisposedException">
346 /// The <see cref="CompositionContainer"/> has been disposed of.
348 public IEnumerable<Lazy<T>> GetExports<T>(string? contractName)
350 return GetExportsCore<T>(contractName);
354 /// Returns the exports with the contract name derived from the specified type parameter.
356 /// <typeparam name="T">
357 /// The type of the <see cref="Lazy{T, TMetadataView}"/> objects to return. The
358 /// contract name is also derived from this type parameter.
360 /// <typeparam name="TMetadataView">
361 /// The type of the metadata view of the <see cref="Lazy{T, TMetadataView}"/> objects
365 /// An <see cref="IEnumerable{T}"/> containing the
366 /// <see cref="Lazy{T, TMetadataView}"/> objects with the contract name derived from
367 /// <typeparamref name="T"/>, if found; otherwise, an empty
368 /// <see cref="IEnumerable{T}"/>.
372 /// The contract name is the result of calling
373 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
376 /// The contract name is compared using a case-sensitive, non-linguistic comparison
377 /// using <see cref="StringComparer.Ordinal"/>.
380 /// <exception cref="InvalidOperationException">
381 /// <typeparamref name="TMetadataView"/> is not a valid metadata view type.
383 /// <exception cref="ObjectDisposedException">
384 /// The <see cref="CompositionContainer"/> has been disposed of.
386 public IEnumerable<Lazy<T, TMetadataView>> GetExports<T, TMetadataView>()
388 return GetExports<T, TMetadataView>((string?)null);
392 /// Returns the exports with the specified contract name.
394 /// <typeparam name="T">
395 /// The type of the <see cref="Lazy{T, TMetadataView}"/> objects to return. The
396 /// contract name is also derived from this type parameter.
398 /// <typeparam name="TMetadataView">
399 /// The type of the metadata view of the <see cref="Lazy{T, TMetadataView}"/> objects
402 /// <param name="contractName">
403 /// A <see cref="string"/> containing the contract name of the
404 /// <see cref="Lazy{T, TMetadataView}"/> objects to return; or <see langword="null"/>
405 /// or an empty string ("") to use the default contract name.
408 /// An <see cref="IEnumerable{T}"/> containing the
409 /// <see cref="Lazy{T, TMetadataView}"/> objects with the specified contract name if
410 /// found; otherwise, an empty <see cref="IEnumerable{T}"/>.
414 /// The default contract name is the result of calling
415 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
418 /// The contract name is compared using a case-sensitive, non-linguistic comparison
419 /// using <see cref="StringComparer.Ordinal"/>.
422 /// <exception cref="InvalidOperationException">
423 /// <typeparamref name="TMetadataView"/> is not a valid metadata view type.
425 /// <exception cref="ObjectDisposedException">
426 /// The <see cref="CompositionContainer"/> has been disposed of.
428 public IEnumerable<Lazy<T, TMetadataView>> GetExports<T, TMetadataView>(string? contractName)
430 return GetExportsCore<T, TMetadataView>(contractName);
434 /// Returns the exported value with the contract name derived from the specified type
435 /// parameter, throwing an exception if there is not exactly one matching exported value.
437 /// <typeparam name="T">
438 /// The type of the exported value to return. The contract name is also
439 /// derived from this type parameter.
442 /// The exported <see cref="object"/> with the contract name derived from
443 /// <typeparamref name="T"/>.
447 /// The contract name is the result of calling
448 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
451 /// The contract name is compared using a case-sensitive, non-linguistic comparison
452 /// using <see cref="StringComparer.Ordinal"/>.
455 /// <exception cref="CompositionContractMismatchException">
456 /// The underlying exported value cannot be cast to <typeparamref name="T"/>.
458 /// <exception cref="ImportCardinalityMismatchException">
460 /// There are zero exported values with the contract name derived from
461 /// <typeparamref name="T"/> in the <see cref="CompositionContainer"/>.
465 /// There are more than one exported values with the contract name derived from
466 /// <typeparamref name="T"/> in the <see cref="CompositionContainer"/>.
469 /// <exception cref="ObjectDisposedException">
470 /// The <see cref="CompositionContainer"/> has been disposed of.
472 /// <exception cref="CompositionException">
473 /// An error occurred during composition. <see cref="CompositionException.Errors"/> will
474 /// contain a collection of errors that occurred.
476 public T? GetExportedValue<T>()
478 return GetExportedValue<T>((string?)null);
482 /// Returns the exported value with the specified contract name, throwing an exception
483 /// if there is not exactly one matching exported value.
485 /// <typeparam name="T">
486 /// The type of the exported value to return.
488 /// <param name="contractName">
489 /// A <see cref="string"/> containing the contract name of the exported value to return,
490 /// or <see langword="null"/> or an empty string ("") to use the default contract name.
493 /// The exported <see cref="object"/> with the specified contract name.
497 /// The default contract name is the result of calling
498 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
501 /// The contract name is compared using a case-sensitive, non-linguistic comparison
502 /// using <see cref="StringComparer.Ordinal"/>.
505 /// <exception cref="CompositionContractMismatchException">
506 /// The underlying exported value cannot be cast to <typeparamref name="T"/>.
508 /// <exception cref="ImportCardinalityMismatchException">
510 /// There are zero exported values with the specified contract name in the
511 /// <see cref="CompositionContainer"/>.
515 /// There are more than one exported values with the specified contract name in the
516 /// <see cref="CompositionContainer"/>.
519 /// <exception cref="ObjectDisposedException">
520 /// The <see cref="CompositionContainer"/> has been disposed of.
522 /// <exception cref="CompositionException">
523 /// An error occurred during composition. <see cref="CompositionException.Errors"/> will
524 /// contain a collection of errors that occurred.
526 public T? GetExportedValue<T>(string? contractName)
528 return GetExportedValueCore<T>(contractName, ImportCardinality.ExactlyOne);
532 /// Returns the exported value with the contract name derived from the specified type
533 /// parameter, throwing an exception if there is more than one matching exported value.
535 /// <typeparam name="T">
536 /// The type of the exported value to return. The contract name is also
537 /// derived from this type parameter.
540 /// The exported <see cref="object"/> with the contract name derived from
541 /// <typeparamref name="T"/>, if found; otherwise, the default value for
542 /// <typeparamref name="T"/>.
546 /// If the exported value is not found, then this method returns the appropriate
547 /// default value for <typeparamref name="T"/>; for example, 0 (zero) for integer
548 /// types, <see langword="false"/> for Boolean types, and <see langword="null"/>
549 /// for reference types.
552 /// The contract name is the result of calling
553 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
556 /// The contract name is compared using a case-sensitive, non-linguistic comparison
557 /// using <see cref="StringComparer.Ordinal"/>.
560 /// <exception cref="CompositionContractMismatchException">
561 /// The underlying exported value cannot be cast to <typeparamref name="T"/>.
563 /// <exception cref="ImportCardinalityMismatchException">
565 /// There are more than one exported values with the contract name derived from
566 /// <typeparamref name="T"/> in the <see cref="CompositionContainer"/>.
569 /// <exception cref="ObjectDisposedException">
570 /// The <see cref="CompositionContainer"/> has been disposed of.
572 /// <exception cref="CompositionException">
573 /// An error occurred during composition. <see cref="CompositionException.Errors"/> will
574 /// contain a collection of errors that occurred.
576 public T? GetExportedValueOrDefault<T>()
578 return GetExportedValueOrDefault<T>((string?)null);
582 /// Returns the exported value with the specified contract name, throwing an exception
583 /// if there is more than one matching exported value.
585 /// <typeparam name="T">
586 /// The type of the exported value to return.
588 /// <param name="contractName">
589 /// A <see cref="string"/> containing the contract name of the exported value to return,
590 /// or <see langword="null"/> or an empty string ("") to use the default contract name.
593 /// The exported <see cref="object"/> with the specified contract name, if found;
594 /// otherwise, the default value for <typeparamref name="T"/>.
598 /// If the exported value is not found, then this method returns the appropriate
599 /// default value for <typeparamref name="T"/>; for example, 0 (zero) for integer
600 /// types, <see langword="false"/> for Boolean types, and <see langword="null"/>
601 /// for reference types.
604 /// The default contract name is the result of calling
605 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
608 /// The contract name is compared using a case-sensitive, non-linguistic comparison
609 /// using <see cref="StringComparer.Ordinal"/>.
612 /// <exception cref="CompositionContractMismatchException">
613 /// The underlying exported value cannot be cast to <typeparamref name="T"/>.
615 /// <exception cref="ImportCardinalityMismatchException">
616 /// There are more than one exported values with the specified contract name in the
617 /// <see cref="CompositionContainer"/>.
619 /// <exception cref="ObjectDisposedException">
620 /// The <see cref="CompositionContainer"/> has been disposed of.
622 /// <exception cref="CompositionException">
623 /// An error occurred during composition. <see cref="CompositionException.Errors"/> will
624 /// contain a collection of errors that occurred.
626 public T? GetExportedValueOrDefault<T>(string? contractName)
628 return GetExportedValueCore<T>(contractName, ImportCardinality.ZeroOrOne);
632 /// Returns the exported values with the contract name derived from the specified type
635 /// <typeparam name="T">
636 /// The type of the exported value to return. The contract name is also
637 /// derived from this type parameter.
640 /// An <see cref="Collection{T}"/> containing the exported values with the contract name
641 /// derived from the specified type parameter, if found; otherwise, an empty
642 /// <see cref="Collection{T}"/>.
646 /// The contract name is the result of calling
647 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
650 /// The contract name is compared using a case-sensitive, non-linguistic comparison
651 /// using <see cref="StringComparer.Ordinal"/>.
654 /// <exception cref="CompositionContractMismatchException">
655 /// One or more of the underlying exported values cannot be cast to
656 /// <typeparamref name="T"/>.
658 /// <exception cref="ObjectDisposedException">
659 /// The <see cref="CompositionContainer"/> has been disposed of.
661 /// <exception cref="CompositionException">
662 /// An error occurred during composition. <see cref="CompositionException.Errors"/> will
663 /// contain a collection of errors that occurred.
665 public IEnumerable<T> GetExportedValues<T>()
667 return GetExportedValues<T>((string?)null);
671 /// Returns the exported values with the specified contract name.
673 /// <typeparam name="T">
674 /// The type of the exported value to return.
676 /// <param name="contractName">
677 /// A <see cref="string"/> containing the contract name of the exported values to
678 /// return; or <see langword="null"/> or an empty string ("") to use the default
682 /// An <see cref="Collection{T}"/> containing the exported values with the specified
683 /// contract name, if found; otherwise, an empty <see cref="Collection{T}"/>.
687 /// The default contract name is the result of calling
688 /// <see cref="AttributedModelServices.GetContractName(Type)"/> on <typeparamref name="T"/>.
691 /// The contract name is compared using a case-sensitive, non-linguistic comparison
692 /// using <see cref="StringComparer.Ordinal"/>.
695 /// <exception cref="CompositionContractMismatchException">
696 /// One or more of the underlying exported values cannot be cast to
697 /// <typeparamref name="T"/>.
699 /// <exception cref="ObjectDisposedException">
700 /// The <see cref="CompositionContainer"/> has been disposed of.
702 /// <exception cref="CompositionException">
703 /// An error occurred during composition. <see cref="CompositionException.Errors"/> will
704 /// contain a collection of errors that occurred.
706 public IEnumerable<T> GetExportedValues<T>(string? contractName)
708 return GetExportedValuesCore<T>(contractName);
711 private IEnumerable<T> GetExportedValuesCore<T>(string? contractName)
713 IEnumerable<Export> exports = GetExportsCore(typeof(T), (Type?)null, contractName, ImportCardinality.ZeroOrMore);
715 Collection<T> result = new Collection<T>();
716 foreach (Export export in exports)
718 result.Add(ExportServices.GetCastedExportedValue<T>(export));
723 private T? GetExportedValueCore<T>(string? contractName, ImportCardinality cardinality)
725 if (!cardinality.IsAtMostOne())
727 throw new Exception(SR.Diagnostic_InternalExceptionMessage);
730 Export? export = GetExportsCore(typeof(T), (Type?)null, contractName, cardinality).SingleOrDefault();
732 return (export != null) ? ExportServices.GetCastedExportedValue<T>(export) : default;
735 private IEnumerable<Lazy<T>> GetExportsCore<T>(string? contractName)
737 IEnumerable<Export> exports = GetExportsCore(typeof(T), (Type?)null, contractName, ImportCardinality.ZeroOrMore);
739 Collection<Lazy<T>> result = new Collection<Lazy<T>>();
740 foreach (Export export in exports)
742 result.Add(ExportServices.CreateStronglyTypedLazyOfT<T>(export));
747 private IEnumerable<Lazy<T, TMetadataView>> GetExportsCore<T, TMetadataView>(string? contractName)
749 IEnumerable<Export> exports = GetExportsCore(typeof(T), typeof(TMetadataView), contractName, ImportCardinality.ZeroOrMore);
751 Collection<Lazy<T, TMetadataView>> result = new Collection<Lazy<T, TMetadataView>>();
752 foreach (Export export in exports)
754 result.Add(ExportServices.CreateStronglyTypedLazyOfTM<T, TMetadataView>(export));
759 private Lazy<T, TMetadataView>? GetExportCore<T, TMetadataView>(string? contractName)
761 Export? export = GetExportsCore(typeof(T), typeof(TMetadataView), contractName, ImportCardinality.ExactlyOne).SingleOrDefault();
763 return (export != null) ? ExportServices.CreateStronglyTypedLazyOfTM<T, TMetadataView>(export) : null;
766 private Lazy<T>? GetExportCore<T>(string? contractName)
768 Export? export = GetExportsCore(typeof(T), null, contractName, ImportCardinality.ExactlyOne).SingleOrDefault();
770 return (export != null) ? ExportServices.CreateStronglyTypedLazyOfT<T>(export) : null;
773 private IEnumerable<Export> GetExportsCore(Type type, Type? metadataViewType, string? contractName, ImportCardinality cardinality)
775 // Only 'type' cannot be null - the other parameters have sensible defaults.
776 Requires.NotNull(type, nameof(type));
778 if (string.IsNullOrEmpty(contractName))
780 contractName = AttributedModelServices.GetContractName(type);
783 metadataViewType ??= ExportServices.DefaultMetadataViewType;
785 if (!MetadataViewProvider.IsViewTypeValid(metadataViewType))
787 throw new InvalidOperationException(SR.Format(SR.InvalidMetadataView, metadataViewType.Name));
790 ImportDefinition importDefinition = BuildImportDefinition(type, metadataViewType, contractName, cardinality);
791 return GetExports(importDefinition, null);
794 private static ImportDefinition BuildImportDefinition(Type type, Type metadataViewType, string contractName, ImportCardinality cardinality)
796 ArgumentNullException.ThrowIfNull(type);
797 ArgumentNullException.ThrowIfNull(metadataViewType);
798 ArgumentNullException.ThrowIfNull(contractName);
800 IEnumerable<KeyValuePair<string, Type>> requiredMetadata = CompositionServices.GetRequiredMetadata(metadataViewType);
801 IDictionary<string, object?> metadata = CompositionServices.GetImportMetadata(type, null);
803 string? requiredTypeIdentity = null;
804 if (type != typeof(object))
806 requiredTypeIdentity = AttributedModelServices.GetTypeIdentity(type);
809 return new ContractBasedImportDefinition(contractName, requiredTypeIdentity, requiredMetadata, cardinality, false, true, CreationPolicy.Any, metadata);