1
// -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
5 using System
.Collections
.Generic
;
6 using System
.ComponentModel
.Composition
.Primitives
;
7 using System
.Globalization
;
9 using System
.Linq
.Expressions
;
10 using System
.Threading
;
11 using Microsoft
.Internal
;
13 namespace System
.ComponentModel
.Composition
.Hosting
16 /// A mutable collection of <see cref="ComposablePartCatalog"/>s.
19 /// This type is thread safe.
21 public class AggregateCatalog
: ComposablePartCatalog
, INotifyComposablePartCatalogChanged
23 private ComposablePartCatalogCollection _catalogs
= null;
24 private volatile int _isDisposed
= 0;
25 private IQueryable
<ComposablePartDefinition
> _partsQuery
;
28 /// Initializes a new instance of the <see cref="AggregateCatalog"/> class.
30 public AggregateCatalog()
31 : this((IEnumerable
<ComposablePartCatalog
>)null)
36 /// Initializes a new instance of the <see cref="AggregateCatalog"/> class
37 /// with the specified catalogs.
39 /// <param name="catalogs">
40 /// An <see cref="Array"/> of <see cref="ComposablePartCatalog"/> objects to add to the
41 /// <see cref="AggregateCatalog"/>.
43 /// <exception cref="ArgumentNullException">
44 /// <paramref name="catalogs"/> is <see langword="null"/>.
46 /// <exception cref="ArgumentException">
47 /// <paramref name="catalogs"/> contains an element that is <see langword="null"/>.
49 public AggregateCatalog(params ComposablePartCatalog
[] catalogs
)
50 : this((IEnumerable
<ComposablePartCatalog
>)catalogs
)
55 /// Initializes a new instance of the <see cref="AggregateCatalog"/> class
56 /// with the specified catalogs.
58 /// <param name="catalogs">
59 /// An <see cref="IEnumerable{T}"/> of <see cref="ComposablePartCatalog"/> objects to add
60 /// to the <see cref="AggregateCatalog"/>; or <see langword="null"/> to
61 /// create an <see cref="AggregateCatalog"/> that is empty.
63 /// <exception cref="ArgumentException">
64 /// <paramref name="catalogs"/> contains an element that is <see langword="null"/>.
66 public AggregateCatalog(IEnumerable
<ComposablePartCatalog
> catalogs
)
68 Requires
.NullOrNotNullElements(catalogs
, "catalogs");
70 this._catalogs
= new ComposablePartCatalogCollection(catalogs
, this.OnChanged
, this.OnChanging
);
71 this._partsQuery
= this._catalogs
.AsQueryable().SelectMany(catalog
=> catalog
.Parts
);
75 /// Notify when the contents of the Catalog has changed.
77 public event EventHandler
<ComposablePartCatalogChangeEventArgs
> Changed
81 this._catalogs
.Changed
+= value;
85 this._catalogs
.Changed
-= value;
90 /// Notify when the contents of the Catalog has changing.
92 public event EventHandler
<ComposablePartCatalogChangeEventArgs
> Changing
96 this._catalogs
.Changing
+= value;
100 this._catalogs
.Changing
-= value;
105 /// Gets the part definitions of the catalog.
108 /// A <see cref="IQueryable{T}"/> of <see cref="ComposablePartDefinition"/> objects of the
109 /// <see cref="AggregateCatalog"/>.
111 /// <exception cref="ObjectDisposedException">
112 /// The <see cref="AggregateCatalog"/> has been disposed of.
114 public override IQueryable
<ComposablePartDefinition
> Parts
118 this.ThrowIfDisposed();
119 return this._partsQuery
;
124 /// Returns the export definitions that match the constraint defined by the specified definition.
126 /// <param name="definition">
127 /// The <see cref="ImportDefinition"/> that defines the conditions of the
128 /// <see cref="ExportDefinition"/> objects to return.
131 /// An <see cref="IEnumerable{T}"/> of <see cref="Tuple{T1, T2}"/> containing the
132 /// <see cref="ExportDefinition"/> objects and their associated
133 /// <see cref="ComposablePartDefinition"/> for objects that match the constraint defined
134 /// by <paramref name="definition"/>.
136 /// <exception cref="ArgumentNullException">
137 /// <paramref name="definition"/> is <see langword="null"/>.
139 /// <exception cref="ObjectDisposedException">
140 /// The <see cref="AggregateCatalog"/> has been disposed of.
142 public override IEnumerable
<Tuple
<ComposablePartDefinition
, ExportDefinition
>> GetExports(ImportDefinition definition
)
144 this.ThrowIfDisposed();
146 Requires
.NotNull(definition
, "definition");
148 // delegate the query to each catalog and merge the results.
149 var exports
= new List
<Tuple
<ComposablePartDefinition
, ExportDefinition
>>();
150 foreach (var catalog
in this._catalogs
)
152 foreach (var export
in catalog
.GetExports(definition
))
161 /// Gets the underlying catalogs of the catalog.
164 /// An <see cref="ICollection{T}"/> of underlying <see cref="ComposablePartCatalog"/> objects
165 /// of the <see cref="AggregateCatalog"/>.
167 /// <exception cref="ObjectDisposedException">
168 /// The <see cref="AggregateCatalog"/> has been disposed of.
170 public ICollection
<ComposablePartCatalog
> Catalogs
174 this.ThrowIfDisposed();
175 return this._catalogs
;
179 protected override void Dispose(bool disposing
)
185 // NOTE : According to http://msdn.microsoft.com/en-us/library/4bw5ewxy.aspx, the warning is bogus when used with Interlocked API.
186 #pragma warning disable 420
187 if (Interlocked
.CompareExchange(ref this._isDisposed
, 1, 0) == 0)
188 #pragma warning restore 420
190 this._catalogs
.Dispose();
196 base.Dispose(disposing
);
201 /// Raises the <see cref="INotifyComposablePartCatalogChanged.Changed"/> event.
204 /// An <see cref="ComposablePartCatalogChangeEventArgs"/> containing the data for the event.
206 protected virtual void OnChanged(ComposablePartCatalogChangeEventArgs e
)
208 this._catalogs
.OnChanged(this, e
);
212 /// Raises the <see cref="INotifyComposablePartCatalogChanged.Changing"/> event.
215 /// An <see cref="ComposablePartCatalogChangeEventArgs"/> containing the data for the event.
217 protected virtual void OnChanging(ComposablePartCatalogChangeEventArgs e
)
219 this._catalogs
.OnChanging(this, e
);
222 private void ThrowIfDisposed()
224 if (this._isDisposed
== 1)
226 throw ExceptionBuilder
.CreateObjectDisposed(this);