Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.ComponentModel.Composition / Tests / ComponentModelUnitTest / System / Integration / AdaptingCollectionTests.cs
1 // -----------------------------------------------------------------------\r
2 // Copyright (c) Microsoft Corporation.  All rights reserved.\r
3 // -----------------------------------------------------------------------\r
4 using System;\r
5 using System.Collections.Generic;\r
6 using System.Collections.Specialized;\r
7 using System.ComponentModel.Composition.Hosting;\r
8 using System.ComponentModel.Composition.Primitives;\r
9 using System.Linq;\r
10 using Microsoft.VisualStudio.TestTools.UnitTesting;\r
11 using System.ComponentModel.Composition.Factories;\r
12 \r
13 namespace System.ComponentModel.Composition\r
14 {\r
15     public class FilteringCollection<T, M> : AdaptingCollection<T, M>\r
16     {\r
17         public FilteringCollection(Func<Lazy<T, M>, bool> filter)\r
18             : base(e => e.Where(filter))\r
19         {\r
20         }\r
21     }\r
22 \r
23     public class OrderingCollection<T, M> : AdaptingCollection<T, M>\r
24     {\r
25         public OrderingCollection(Func<Lazy<T, M>, object> keySelector)\r
26             : this(keySelector, false)\r
27         {\r
28         }\r
29 \r
30         public OrderingCollection(Func<Lazy<T, M>, object> keySelector, bool descending)\r
31             : base(e => descending ? e.OrderByDescending(keySelector) : e.OrderBy(keySelector))\r
32         {\r
33         }\r
34     }\r
35 \r
36     public class AdaptingCollection<T> : AdaptingCollection<T, IDictionary<string, object>>\r
37     {\r
38         public AdaptingCollection(Func<IEnumerable<Lazy<T, IDictionary<string, object>>>, \r
39                                        IEnumerable<Lazy<T, IDictionary<string, object>>>> adaptor)\r
40             : base(adaptor)\r
41         {\r
42         }\r
43     }\r
44 \r
45     public class AdaptingCollection<T, M> : ICollection<Lazy<T, M>>, INotifyCollectionChanged\r
46     {\r
47         private readonly List<Lazy<T, M>> _allItems = new List<Lazy<T, M>>();\r
48         private readonly Func<IEnumerable<Lazy<T, M>>, IEnumerable<Lazy<T, M>>> _adaptor = null;\r
49         private List<Lazy<T, M>> _adaptedItems = null;\r
50 \r
51         public AdaptingCollection() : this(null)\r
52         {\r
53         }\r
54 \r
55         public AdaptingCollection(Func<IEnumerable<Lazy<T, M>>, IEnumerable<Lazy<T, M>>> adaptor)\r
56         {\r
57             this._adaptor = adaptor;\r
58         }\r
59 \r
60         public event NotifyCollectionChangedEventHandler CollectionChanged;\r
61 \r
62         public void ReapplyAdaptor()\r
63         {\r
64             if (this._adaptedItems != null)\r
65             {\r
66                 this._adaptedItems = null;\r
67                 this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));\r
68             }\r
69         }\r
70 \r
71         protected virtual IEnumerable<Lazy<T, M>> Adapt(IEnumerable<Lazy<T, M>> collection)\r
72         {\r
73             if (this._adaptor != null)\r
74             {\r
75                 return this._adaptor.Invoke(collection);\r
76             }\r
77 \r
78             return collection;\r
79         }\r
80 \r
81         protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)\r
82         {\r
83             NotifyCollectionChangedEventHandler collectionChanged = this.CollectionChanged;\r
84 \r
85             if (collectionChanged != null)\r
86             {\r
87                 collectionChanged.Invoke(this, e);\r
88             }\r
89         }\r
90 \r
91         private List<Lazy<T, M>> AdaptedItems\r
92         {\r
93             get\r
94             {\r
95                 if (this._adaptedItems == null)\r
96                 {\r
97                     this._adaptedItems = Adapt(this._allItems).ToList();\r
98                 }\r
99 \r
100                 return this._adaptedItems;\r
101             }\r
102         }\r
103 \r
104         #region ICollection Implementation\r
105         // Accessors work directly against adapted collection\r
106         public bool Contains(Lazy<T, M> item)\r
107         {\r
108             return this.AdaptedItems.Contains(item);\r
109         }\r
110 \r
111         public void CopyTo(Lazy<T, M>[] array, int arrayIndex)\r
112         {\r
113             this.AdaptedItems.CopyTo(array, arrayIndex);\r
114         }\r
115 \r
116         public int Count\r
117         {\r
118             get { return this.AdaptedItems.Count; }\r
119         }\r
120 \r
121         public bool IsReadOnly\r
122         {\r
123             get { return false; }\r
124         }\r
125 \r
126         public IEnumerator<Lazy<T, M>> GetEnumerator()\r
127         {\r
128             return this.AdaptedItems.GetEnumerator();\r
129         }\r
130 \r
131         Collections.IEnumerator Collections.IEnumerable.GetEnumerator()\r
132         {\r
133             return this.GetEnumerator();\r
134         }\r
135 \r
136         // Mutation methods work against complete collection\r
137         // and then force a reset of the adapted collection\r
138         public void Add(Lazy<T, M> item)\r
139         {\r
140             this._allItems.Add(item);\r
141             ReapplyAdaptor();\r
142         }\r
143 \r
144         public void Clear()\r
145         {\r
146             this._allItems.Clear();\r
147             ReapplyAdaptor();\r
148         }\r
149 \r
150         public bool Remove(Lazy<T, M> item)\r
151         {\r
152             bool removed = this._allItems.Remove(item);\r
153             ReapplyAdaptor();\r
154             return removed;\r
155         }\r
156         #endregion\r
157     }\r
158 \r
159     [TestClass]\r
160     public class AdaptingCollectionTests\r
161     {\r
162         public interface IContract { }\r
163         public interface INetworkAwareMetadata\r
164         {\r
165             [DefaultValue(false)]\r
166             bool RequiresOnline { get; }\r
167         }\r
168 \r
169         [Export(typeof(IContract))]\r
170         [ExportMetadata("RequiresOnline", true)]\r
171         public class NetworkExport : IContract { }\r
172 \r
173         [Export(typeof(IContract))]\r
174         public class NonNetworkExport : IContract { }\r
175 \r
176         public class FilterExports\r
177         {\r
178             public FilterExports()\r
179             {\r
180                 this.OnlineOnly = new AdaptingCollection<IContract, INetworkAwareMetadata>(e =>\r
181                     e.Where(p => p.Metadata.RequiresOnline));\r
182 \r
183                 this.OnlineOnly2 = new FilteringCollection<IContract, INetworkAwareMetadata>(p => p.Metadata.RequiresOnline);\r
184             }\r
185 \r
186             [ImportMany]\r
187             public AdaptingCollection<IContract, INetworkAwareMetadata> OnlineOnly { get; set; }\r
188 \r
189             [ImportMany]\r
190             public FilteringCollection<IContract, INetworkAwareMetadata> OnlineOnly2 { get; set; }\r
191         }\r
192 \r
193         [TestMethod]\r
194         public void TestFilteringImports()\r
195         {\r
196             var container = ContainerFactory.CreateWithAttributedCatalog(typeof(NetworkExport), typeof(NonNetworkExport));\r
197 \r
198             var filterExports = new FilterExports();\r
199             container.ComposeParts(filterExports);\r
200 \r
201             Assert.AreEqual(1, filterExports.OnlineOnly.Count);\r
202             Assert.AreEqual(1, filterExports.OnlineOnly2.Count);\r
203         }\r
204 \r
205         public interface IOrderMetadata\r
206         {\r
207             [DefaultValue(Int32.MaxValue)]\r
208             int Order { get; }\r
209         }\r
210 \r
211         [Export(typeof(IContract))]\r
212         [ExportMetadata("Order", 2)]\r
213         public class BExport : IContract { }\r
214 \r
215         [Export(typeof(IContract))]\r
216         [ExportMetadata("Order", 1)]\r
217         public class AExport : IContract { }\r
218 \r
219         [Export(typeof(IContract))]\r
220         public class CExport : IContract { }\r
221 \r
222         public class OrderExportsByMetadata\r
223         {\r
224             public OrderExportsByMetadata()\r
225             {\r
226                 this.OrderedItems = new AdaptingCollection<IContract, IOrderMetadata>(e =>\r
227                     e.OrderBy(p => p.Metadata.Order));\r
228 \r
229                 this.OrderedItems2 = new OrderingCollection<IContract, IOrderMetadata>(p => p.Metadata.Order);\r
230             }\r
231 \r
232             [ImportMany]\r
233             public AdaptingCollection<IContract, IOrderMetadata> OrderedItems { get; set; }\r
234 \r
235             [ImportMany]\r
236             public OrderingCollection<IContract, IOrderMetadata> OrderedItems2 { get; set; }\r
237         }\r
238 \r
239         [TestMethod]\r
240         public void TestOrderingImportsByMetadata()\r
241         {\r
242             var container = ContainerFactory.CreateWithAttributedCatalog(typeof(BExport), typeof(AExport), typeof(CExport));\r
243             var orderExports = new OrderExportsByMetadata();\r
244 \r
245             container.ComposeParts(orderExports);\r
246 \r
247             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(0).Value, typeof(AExport));\r
248             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(1).Value, typeof(BExport));\r
249             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(2).Value, typeof(CExport));\r
250 \r
251             Assert.IsInstanceOfType(orderExports.OrderedItems2.ElementAt(0).Value, typeof(AExport));\r
252             Assert.IsInstanceOfType(orderExports.OrderedItems2.ElementAt(1).Value, typeof(BExport));\r
253             Assert.IsInstanceOfType(orderExports.OrderedItems2.ElementAt(2).Value, typeof(CExport));\r
254         }\r
255 \r
256         public class OrderExportsByName\r
257         {\r
258             public OrderExportsByName(bool descending)\r
259             {\r
260                 if (descending)\r
261                 {\r
262                     this.OrderedItems = new AdaptingCollection<IContract>(e =>\r
263                         e.OrderByDescending(p => p.Value.GetType().FullName));\r
264                 }\r
265                 else\r
266                 {\r
267                     this.OrderedItems = new AdaptingCollection<IContract>(e =>\r
268                         e.OrderBy(p => p.Value.GetType().FullName));\r
269                 }\r
270             }\r
271 \r
272             [ImportMany]\r
273             public AdaptingCollection<IContract> OrderedItems { get; set; }\r
274         }\r
275 \r
276 \r
277         [TestMethod]\r
278         public void TestOrderingImportsByTypeName()\r
279         {\r
280             var container = ContainerFactory.CreateWithAttributedCatalog(typeof(BExport), typeof(AExport), typeof(CExport));\r
281             var orderExports = new OrderExportsByName(false);\r
282 \r
283             container.ComposeParts(orderExports);\r
284 \r
285             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(0).Value, typeof(AExport));\r
286             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(1).Value, typeof(BExport));\r
287             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(2).Value, typeof(CExport));\r
288 \r
289             orderExports = new OrderExportsByName(true);\r
290 \r
291             container.ComposeParts(orderExports);\r
292 \r
293             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(0).Value, typeof(CExport));\r
294             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(1).Value, typeof(BExport));\r
295             Assert.IsInstanceOfType(orderExports.OrderedItems.ElementAt(2).Value, typeof(AExport));\r
296         }\r
297 \r
298         public interface IDynamicFilteredMetadata\r
299         {\r
300             bool Dynamic { get; }\r
301         }\r
302 \r
303         [Export(typeof(IContract))]\r
304         [ExportMetadata("Dynamic", true)]\r
305         public class Dynamic1 : IContract { }\r
306 \r
307         [Export(typeof(IContract))]\r
308         [ExportMetadata("Dynamic", true)]\r
309         public class Dynamic2 : IContract { }\r
310 \r
311         [Export(typeof(IContract))]\r
312         [ExportMetadata("Dynamic", false)]\r
313         public class NonDynamic1 : IContract { }\r
314 \r
315         public class DynamicFilteredCollection<T, M> : AdaptingCollection<T, M> where M : IDynamicFilteredMetadata\r
316         {\r
317             public DynamicFilteredCollection()\r
318             {\r
319             }\r
320 \r
321             private bool _includeDynamic = false;\r
322             public bool IncludeDynamic \r
323             {\r
324                 get { return this._includeDynamic; }\r
325                 set \r
326                 {\r
327                     if (this._includeDynamic != value)\r
328                     {\r
329                         this.ReapplyAdaptor();\r
330                     }\r
331 \r
332                     this._includeDynamic = value;\r
333                 }\r
334             }\r
335 \r
336             protected override IEnumerable<Lazy<T, M>> Adapt(IEnumerable<Lazy<T, M>> collection)\r
337             {\r
338                 return collection.Where(p => !p.Metadata.Dynamic || IncludeDynamic);\r
339             }\r
340         }\r
341 \r
342         public class DynamicExports\r
343         {\r
344             [ImportMany]\r
345             public DynamicFilteredCollection<IContract, IDynamicFilteredMetadata> DynamicCollection { get; set; }\r
346         }\r
347 \r
348         [TestMethod]\r
349         public void TestDyamicallyFilteringImports()\r
350         {\r
351             var container = ContainerFactory.CreateWithAttributedCatalog(typeof(Dynamic1), typeof(Dynamic2), typeof(NonDynamic1));\r
352             var dynamicExports = new DynamicExports();\r
353 \r
354             container.ComposeParts(dynamicExports);\r
355 \r
356             Assert.AreEqual(1, dynamicExports.DynamicCollection.Count);\r
357 \r
358             dynamicExports.DynamicCollection.IncludeDynamic = true;\r
359 \r
360             Assert.AreEqual(3, dynamicExports.DynamicCollection.Count);\r
361         }\r
362 \r
363         public class DynamicExportsNoSubType\r
364         {\r
365             public DynamicExportsNoSubType()\r
366             {\r
367                 this.DynamicCollection = new AdaptingCollection<IContract, IDynamicFilteredMetadata>(e =>\r
368                     e.Where(p => !p.Metadata.Dynamic || this.IncludeDynamic));\r
369             }\r
370 \r
371             private bool _includeDynamic = false;\r
372             public bool IncludeDynamic\r
373             {\r
374                 get { return this._includeDynamic; }\r
375                 set\r
376                 {\r
377                     if (this._includeDynamic != value)\r
378                     {\r
379                         this.DynamicCollection.ReapplyAdaptor();\r
380                     }\r
381 \r
382                     this._includeDynamic = value;\r
383                 }\r
384             }\r
385 \r
386             [ImportMany]\r
387             public AdaptingCollection<IContract, IDynamicFilteredMetadata> DynamicCollection { get; set; }\r
388         }\r
389 \r
390         [TestMethod]\r
391         public void TestDyamicallyFilteringNoSubTypeImports()\r
392         {\r
393             var container = ContainerFactory.CreateWithAttributedCatalog(typeof(Dynamic1), typeof(Dynamic2), typeof(NonDynamic1));\r
394             var dynamicExports = new DynamicExportsNoSubType();\r
395 \r
396             container.ComposeParts(dynamicExports);\r
397 \r
398             Assert.AreEqual(1, dynamicExports.DynamicCollection.Count);\r
399 \r
400             dynamicExports.IncludeDynamic = true;\r
401 \r
402             Assert.AreEqual(3, dynamicExports.DynamicCollection.Count);\r
403         }\r
404     }\r
405 }\r