update MEF to preview 9
[mcs.git] / class / System.ComponentModel.Composition / Tests / ComponentModelUnitTest / System / ComponentModel / Composition / CompositionContainerImportTests.cs
blob3c99bdc85a9af8ee530ebf6be597f604832907ca
1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
4 using System;
5 using System.Collections.Generic;
6 using System.ComponentModel.Composition.Factories;
7 using System.ComponentModel.Composition.Hosting;
8 using System.ComponentModel.Composition.Primitives;
9 using System.ComponentModel.Composition.UnitTesting;
10 using System.Linq;
11 using System.Runtime.InteropServices;
12 using System.UnitTesting;
13 using Microsoft.VisualStudio.TestTools.UnitTesting;
15 namespace System.ComponentModel.Composition
17 [TestClass]
18 public class CompositionContainerImportTests
20 // Exporting collectin values is not supported
21 [TestMethod]
22 public void ImportValues()
24 var container = ContainerFactory.Create();
25 Importer importer = new Importer();
26 Exporter exporter42 = new Exporter(42);
28 CompositionBatch batch = new CompositionBatch();
29 batch.AddPart(importer);
30 batch.AddPart(exporter42);
32 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
33 ErrorId.ReflectionModel_ImportNotAssignableFromExport, RetryMode.DoNotRetry, () =>
35 container.Compose(batch);
36 });
39 [TestMethod]
40 public void ImportSingle()
42 var container = ContainerFactory.Create();
43 var importer = new Int32Importer();
44 var exporter = new Int32Exporter(42);
46 CompositionBatch batch = new CompositionBatch();
47 batch.AddPart(importer);
48 batch.AddPart(exporter);
49 container.Compose(batch);
51 Assert.AreEqual(42, importer.Value, "Expecting value to be imported");
55 [TestMethod]
56 public void ImportSingleFromInternal()
58 var container = ContainerFactory.Create();
59 var importer = new Int32Importer();
60 var exporter = new Int32ExporterInternal(42);
62 CompositionBatch batch = new CompositionBatch();
63 batch.AddPart(importer);
64 batch.AddPart(exporter);
65 container.Compose(batch);
67 Assert.AreEqual(42, importer.Value, "Expecting value to be imported");
70 [TestMethod]
71 public void ImportSingleToInternal()
73 var container = ContainerFactory.Create();
74 var importer = new Int32ImporterInternal();
75 var exporter = new Int32Exporter(42);
77 CompositionBatch batch = new CompositionBatch();
78 batch.AddPart(importer);
79 batch.AddPart(exporter);
80 container.Compose(batch);
82 Assert.AreEqual(42, importer.Value, "Expecting value to be imported");
85 [TestMethod]
86 public void ImportSingleIntoCollection()
88 var container = ContainerFactory.Create();
89 var importer = new Int32CollectionImporter();
90 var exporter = new Int32Exporter(42);
92 CompositionBatch batch = new CompositionBatch();
93 batch.AddPart(importer);
94 batch.AddPart(exporter);
95 container.Compose(batch);
97 EnumerableAssert.AreEqual(importer.Values, 42);
100 [TestMethod]
101 public void ImportValuesNameless()
103 var container = ContainerFactory.Create();
104 ImporterNameless importer;
105 ExporterNameless exporter42 = new ExporterNameless(42);
107 CompositionBatch batch = new CompositionBatch();
108 batch.AddPart(importer = new ImporterNameless());
109 batch.AddPart(exporter42);
110 container.Compose(batch);
112 Assert.AreEqual(42, importer.ValueReadWrite);
113 Assert.AreEqual(42, importer.MetadataReadWrite.Value);
116 [TestMethod]
117 public void ImportValueExceptionMissing()
119 var container = ContainerFactory.Create();
120 Importer importer;
122 CompositionBatch batch = new CompositionBatch();
123 batch.AddPart(importer = new Importer());
125 CompositionAssert.ThrowsChangeRejectedError(ErrorId.ImportEngine_PartCannotSetImport,
126 ErrorId.ImportEngine_ImportCardinalityMismatch,
127 RetryMode.DoNotRetry, () =>
129 container.Compose(batch);
133 [TestMethod]
134 public void ImportValueExceptionMultiple()
136 var container = ContainerFactory.Create();
137 Importer importer = new Importer();
138 Exporter exporter42 = new Exporter(42);
139 Exporter exporter6 = new Exporter(6);
141 CompositionBatch batch = new CompositionBatch();
142 batch.AddPart(importer);
143 batch.AddPart(exporter42);
144 batch.AddPart(exporter6);
146 CompositionAssert.ThrowsChangeRejectedError(ErrorId.ImportEngine_PartCannotSetImport,
147 RetryMode.DoNotRetry, () =>
149 container.Compose(batch);
153 [TestMethod]
154 public void ImportValueExceptionSetterException()
156 var container = ContainerFactory.Create();
157 ImporterInvalidSetterException importer = new ImporterInvalidSetterException();
158 Exporter exporter42 = new Exporter(42);
160 CompositionBatch batch = new CompositionBatch();
161 batch.AddPart(importer);
162 batch.AddPart(exporter42);
164 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotActivate,
165 ErrorId.ReflectionModel_ImportThrewException,
166 RetryMode.DoNotRetry, () =>
168 container.Compose(batch);
172 [TestMethod]
173 public void ImportValueExceptionLazily()
175 var catalog = new AssemblyCatalog(typeof(ImportImporterInvalidSetterExceptionLazily).Assembly);
176 var container = ContainerFactory.CreateWithAttributedCatalog(typeof(ImportImporterInvalidSetterExceptionLazily), typeof(ImporterInvalidSetterException));
177 var invalidLazy = container.GetExportedValue<ImportImporterInvalidSetterExceptionLazily>();
179 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotGetExportedValue,
180 ErrorId.ImportEngine_PartCannotActivate,
181 ErrorId.ReflectionModel_ImportThrewException, RetryMode.DoNotRetry, () =>
183 var value = invalidLazy.Value.Value;
187 #if !SILVERLIGHT
189 [TestMethod]
190 public void ImportValueComComponent()
192 CTaskScheduler scheduler = new CTaskScheduler();
196 var container = ContainerFactory.Create();
197 var importer = new ImportComComponent();
199 CompositionBatch batch = new CompositionBatch();
200 batch.AddParts(importer);
201 batch.AddExportedValue<ITaskScheduler>("TaskScheduler", (ITaskScheduler)scheduler);
203 container.Compose(batch);
205 Assert.AreEqual(scheduler, importer.TaskScheduler);
207 finally
209 Marshal.ReleaseComObject(scheduler);
213 [TestMethod]
214 public void DelayImportValueComComponent()
216 CTaskScheduler scheduler = new CTaskScheduler();
220 var container = ContainerFactory.Create();
221 var importer = new DelayImportComComponent();
223 CompositionBatch batch = new CompositionBatch();
224 batch.AddParts(importer);
225 batch.AddExportedValue<ITaskScheduler>("TaskScheduler", (ITaskScheduler)scheduler);
227 container.Compose(batch);
229 Assert.AreEqual(scheduler, importer.TaskScheduler.Value);
231 finally
233 Marshal.ReleaseComObject(scheduler);
236 #endif
238 [TestMethod]
239 [TestProperty("Type", "Integration")]
240 public void OptionalImportsOfValueTypesAreBoundToDefaultWhenNotSatisfied()
242 var container = ContainerFactory.Create();
243 var importer = new OptionalImport();
245 CompositionBatch batch = new CompositionBatch();
246 batch.AddPart(importer);
247 container.Compose(batch);
249 Assert.AreEqual(1, importer.ValueTypeSetCount);
250 Assert.AreEqual(0, importer.ValueType);
253 [TestMethod]
254 [TestProperty("Type", "Integration")]
255 public void OptionalImportsOfNullableValueTypesAreBoundToDefaultWhenNotSatisfied()
257 var container = ContainerFactory.Create();
258 var importer = new OptionalImport();
260 CompositionBatch batch = new CompositionBatch();
261 batch.AddPart(importer);
262 container.Compose(batch);
264 Assert.AreEqual(1, importer.NullableValueTypeSetCount);
265 Assert.IsNull(importer.NullableValueType);
268 [TestMethod]
269 [TestProperty("Type", "Integration")]
270 public void OptionalImportsOfReferenceTypesAreBoundToDefaultWhenNotSatisfied()
272 var container = ContainerFactory.Create();
273 var importer = new OptionalImport();
275 CompositionBatch batch = new CompositionBatch();
276 batch.AddPart(importer);
277 container.Compose(batch);
279 Assert.AreEqual(1, importer.ReferenceTypeSetCount);
280 Assert.IsNull(importer.ReferenceType);
283 [TestMethod]
284 [TestProperty("Type", "Integration")]
285 public void OptionalImportsOfExportValueTypesAreBoundToDefaultWhenNotSatisfied()
287 var container = ContainerFactory.Create();
288 var importer = new OptionalExport();
290 CompositionBatch batch = new CompositionBatch();
291 batch.AddPart(importer);
292 container.Compose(batch);
294 Assert.AreEqual(1, importer.ValueTypeSetCount);
295 Assert.IsNull(importer.ValueType);
298 [TestMethod]
299 [TestProperty("Type", "Integration")]
300 public void OptionalImportsOfExportNullableValueTypesAreBoundToDefaultWhenNotSatisfied()
302 var container = ContainerFactory.Create();
303 var importer = new OptionalExport();
305 CompositionBatch batch = new CompositionBatch();
306 batch.AddPart(importer);
307 container.Compose(batch);
309 Assert.AreEqual(1, importer.NullableValueTypeSetCount);
310 Assert.IsNull(importer.NullableValueType);
313 [TestMethod]
314 [TestProperty("Type", "Integration")]
315 public void OptionalImportsOfExportReferenceTypesAreBoundToDefaultWhenNotSatisfied()
317 var container = ContainerFactory.Create();
318 var importer = new OptionalExport();
320 CompositionBatch batch = new CompositionBatch();
321 batch.AddPart(importer);
322 container.Compose(batch);
324 Assert.AreEqual(1, importer.ReferenceTypeSetCount);
325 Assert.IsNull(importer.ReferenceType);
328 [TestMethod]
329 [TestProperty("Type", "Integration")]
330 public void OptionalImportsOfValueTypesAreReboundToDefaultWhenExportIsRemoved()
332 var container = ContainerFactory.Create();
333 var importer = new OptionalImport();
335 CompositionBatch batch = new CompositionBatch();
336 batch.AddPart(importer);
337 var key = batch.AddExportedValue("ValueType", 10);
339 container.Compose(batch);
341 Assert.AreEqual(1, importer.ValueTypeSetCount);
342 Assert.AreEqual(10, importer.ValueType);
344 batch = new CompositionBatch();
345 batch.RemovePart(key);
346 container.Compose(batch);
348 Assert.AreEqual(2, importer.ValueTypeSetCount);
349 Assert.AreEqual(0, importer.ValueType);
352 [TestMethod]
353 [TestProperty("Type", "Integration")]
354 public void OptionalImportsOfNullableValueTypesAreReboundToDefaultWhenExportIsRemoved()
356 var container = ContainerFactory.Create();
357 var importer = new OptionalImport();
359 CompositionBatch batch = new CompositionBatch();
360 batch.AddPart(importer);
361 var key = batch.AddExportedValue<int?>("NullableValueType", 10);
363 container.Compose(batch);
364 Assert.AreEqual(1, importer.NullableValueTypeSetCount);
365 Assert.AreEqual(10, importer.NullableValueType);
367 batch = new CompositionBatch();
368 batch.RemovePart(key);
369 container.Compose(batch);
371 Assert.AreEqual(2, importer.NullableValueTypeSetCount);
372 Assert.IsNull(importer.NullableValueType);
375 [TestMethod]
376 [TestProperty("Type", "Integration")]
377 public void OptionalImportsOfReferenceTypesAreReboundToDefaultWhenExportIsRemoved()
379 var container = ContainerFactory.Create();
380 var importer = new OptionalImport();
382 CompositionBatch batch = new CompositionBatch();
383 batch.AddPart(importer);
384 var key = batch.AddExportedValue("ReferenceType", "Bar");
386 container.Compose(batch);
387 Assert.AreEqual(1, importer.ReferenceTypeSetCount);
388 Assert.AreEqual("Bar", importer.ReferenceType);
390 batch = new CompositionBatch();
391 batch.RemovePart(key);
392 container.Compose(batch);
394 Assert.AreEqual(2, importer.ReferenceTypeSetCount);
395 Assert.IsNull(importer.ReferenceType);
398 [TestMethod]
399 [TestProperty("Type", "Integration")]
400 public void OptionalImportsOfExportValueTypesAreReboundToDefaultWhenExportIsRemoved()
402 var container = ContainerFactory.Create();
403 var importer = new OptionalExport();
405 CompositionBatch batch = new CompositionBatch();
406 batch.AddPart(importer);
407 var key = batch.AddExportedValue("ValueType", 10);
409 container.Compose(batch);
411 Assert.AreEqual(1, importer.ValueTypeSetCount);
412 Assert.AreEqual(10, importer.ValueType.Value);
414 batch = new CompositionBatch();
415 batch.RemovePart(key);
416 container.Compose(batch);
418 Assert.AreEqual(2, importer.ValueTypeSetCount);
419 Assert.IsNull(importer.ValueType);
422 [TestMethod]
423 [TestProperty("Type", "Integration")]
424 public void OptionalImportsOfExportNullableValueTypesAreReboundToDefaultWhenExportIsRemoved()
426 var container = ContainerFactory.Create();
427 var importer = new OptionalExport();
429 CompositionBatch batch = new CompositionBatch();
430 batch.AddPart(importer);
431 var key = batch.AddExportedValue<int?>("NullableValueType", 10);
433 container.Compose(batch);
434 Assert.AreEqual(1, importer.NullableValueTypeSetCount);
435 Assert.AreEqual(10, importer.NullableValueType.Value);
437 batch = new CompositionBatch();
438 batch.RemovePart(key);
439 container.Compose(batch);
441 Assert.AreEqual(2, importer.NullableValueTypeSetCount);
442 Assert.IsNull(importer.NullableValueType);
445 [TestMethod]
446 [TestProperty("Type", "Integration")]
447 public void OptionalImportsOfExportReferenceTypesAreReboundToDefaultWhenExportIsRemoved()
449 var container = ContainerFactory.Create();
450 var importer = new OptionalExport();
452 CompositionBatch batch = new CompositionBatch();
453 batch.AddPart(importer);
454 var key = batch.AddExportedValue("ReferenceType", "Bar");
456 container.Compose(batch);
457 Assert.AreEqual(1, importer.ReferenceTypeSetCount);
458 Assert.AreEqual("Bar", importer.ReferenceType.Value);
460 batch = new CompositionBatch();
461 batch.RemovePart(key);
462 container.Compose(batch);
464 Assert.AreEqual(2, importer.ReferenceTypeSetCount);
465 Assert.IsNull(importer.ReferenceType);
468 public class OptionalImport
470 public int ValueTypeSetCount;
471 public int NullableValueTypeSetCount;
472 public int ReferenceTypeSetCount;
474 private int _valueType;
475 private int? _nullableValueType;
476 private string _referenceType;
478 [Import("ValueType", AllowDefault = true, AllowRecomposition = true)]
479 public int ValueType
481 get { return _valueType; }
484 ValueTypeSetCount++;
485 _valueType = value;
489 [Import("NullableValueType", AllowDefault = true, AllowRecomposition = true)]
490 public int? NullableValueType
492 get { return _nullableValueType; }
495 NullableValueTypeSetCount++;
496 _nullableValueType = value;
500 [Import("ReferenceType", AllowDefault = true, AllowRecomposition = true)]
501 public string ReferenceType
503 get { return _referenceType; }
504 set
506 ReferenceTypeSetCount++;
507 _referenceType = value;
512 public class OptionalExport
514 public int ValueTypeSetCount;
515 public int NullableValueTypeSetCount;
516 public int ReferenceTypeSetCount;
518 private Lazy<int> _valueType;
519 private Lazy<int?> _nullableValueType;
520 private Lazy<string> _referenceType;
522 [Import("ValueType", AllowDefault = true, AllowRecomposition = true)]
523 public Lazy<int> ValueType
525 get { return _valueType; }
528 ValueTypeSetCount++;
529 _valueType = value;
533 [Import("NullableValueType", AllowDefault = true, AllowRecomposition = true)]
534 public Lazy<int?> NullableValueType
536 get { return _nullableValueType; }
539 NullableValueTypeSetCount++;
540 _nullableValueType = value;
544 [Import("ReferenceType", AllowDefault = true, AllowRecomposition = true)]
545 public Lazy<string> ReferenceType
547 get { return _referenceType; }
550 ReferenceTypeSetCount++;
551 _referenceType = value;
556 private class DelayDuckImporter
558 [Import("Duck")]
559 public Lazy<IDuck> Duck
561 get;
562 set;
566 private class DuckImporter
568 [Import("Duck")]
569 public IDuck Duck
571 get;
572 set;
576 public class QuackLikeADuck
578 public virtual string Quack()
580 return "Quack";
584 public interface IDuck
586 string Quack();
589 #if !SILVERLIGHT
591 [ComImport]
592 [Guid("148BD52A-A2AB-11CE-B11F-00AA00530503")]
593 private class CTaskScheduler
594 { // This interface doesn't implement
595 // ITaskScheduler deliberately
598 [Guid("148BD527-A2AB-11CE-B11F-00AA00530503")]
599 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
600 private interface ITaskScheduler
602 void FakeMethod();
605 private class ImportComComponent
607 [Import("TaskScheduler")]
608 public ITaskScheduler TaskScheduler
610 get;
611 set;
615 private class DelayImportComComponent
617 [Import("TaskScheduler")]
618 public Lazy<ITaskScheduler> TaskScheduler
620 get;
621 set;
625 #endif
627 public class Importer
629 public Importer()
633 [Import("Value")]
634 public int ValueReadWrite { get; set; }
636 [ImportMany("Value")]
637 public IList<int> SingleValueCollectionReadWrite { get; set; }
639 [Import("EmptyValue", AllowDefault = true)]
640 public int ValueEmptyOptional { get; set; }
642 [ImportMany("CollectionValue", typeof(IList<int>))]
643 public IList<int> ValueCollection { get; set; }
647 public class ImporterNameless
650 public ImporterNameless()
654 [Import]
655 public int ValueReadWrite { get; set; }
657 [Import]
658 public Lazy<int> MetadataReadWrite { get; set; }
662 public class ImporterInvalidWrongType
664 [Import("Value")]
665 public DateTime ValueReadWrite { get; set; }
668 [Export]
669 public class ImporterInvalidSetterException
671 [ImportMany("Value")]
672 public IEnumerable<int> ValueReadWrite { get { return null; } set { throw new InvalidOperationException(); } }
675 [Export]
676 public class ImportImporterInvalidSetterExceptionLazily
678 [Import]
679 public Lazy<ImporterInvalidSetterException> Value { get; set; }
683 [PartNotDiscoverable]
684 public class Exporter
686 List<int> collectionValue = new List<int>();
688 public Exporter(int value)
690 Value = value;
693 [Export("Value")]
694 public int Value { get; set; }
697 [Export("CollectionValue")]
698 public IList<int> CollectionValue { get { return collectionValue; } }
702 public class ExporterNameless
705 public ExporterNameless(int value)
707 Value = value;
710 [Export]
711 public int Value { get; set; }
715 public class ExportsString
717 [Export]
718 public string ExportedString = "Test";
721 public class ExportsInvalidListOfExportOfString
723 [Export(typeof(List<Lazy<string>>))]
724 public string ExportedString = "Test";
727 public class ExportsValidListOfExportOfString
729 [Export(typeof(List<Lazy<string>>))]
730 public List<Lazy<string>> ExportedString = new List<Lazy<string>>();
733 [Export]
734 public class ImportsListOfExportOfString
736 [Import(AllowDefault = true)]
737 public List<Lazy<string>> ExportedList { get; set; }
740 [TestMethod]
741 public void ImportListOfExportWithOnlySingleElementsAvailable_ShouldNotFindExport()
743 var container = ContainerFactory.CreateWithAttributedCatalog(typeof(ExportsString), typeof(ImportsListOfExportOfString));
744 var importer = container.GetExportedValue<ImportsListOfExportOfString>();
745 Assert.IsNull(importer.ExportedList);
747 var part = AttributedModelServices.CreatePartDefinition(typeof(ImportsListOfExportOfString), null);
748 var contract = AttributedModelServices.GetContractName(typeof(List<Lazy<string>>));
749 Assert.AreEqual(contract, ((ContractBasedImportDefinition)part.ImportDefinitions.First()).ContractName);
752 [TestMethod]
753 public void ImportListOfExportWithInvalidCollectionAvailable_ShouldThrowMismatch()
755 var container = ContainerFactory.CreateWithAttributedCatalog(typeof(ExportsInvalidListOfExportOfString), typeof(ImportsListOfExportOfString));
757 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotGetExportedValue, () =>
758 container.GetExportedValue<ImportsListOfExportOfString>());
761 [TestMethod]
762 public void ImportListOfExportWithValidCollectionAvailable_ShouldSatisfyImport()
764 var container = ContainerFactory.CreateWithAttributedCatalog(typeof(ExportsValidListOfExportOfString), typeof(ImportsListOfExportOfString));
765 var importer = container.GetExportedValue<ImportsListOfExportOfString>();
766 Assert.AreEqual(0, importer.ExportedList.Count);