1
// -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
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
;
11 using System
.Runtime
.InteropServices
;
12 using System
.UnitTesting
;
13 using Microsoft
.VisualStudio
.TestTools
.UnitTesting
;
15 namespace System
.ComponentModel
.Composition
18 public class CompositionContainerImportTests
20 // Exporting collectin values is not supported
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
);
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");
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");
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");
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);
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
);
117 public void ImportValueExceptionMissing()
119 var container
= ContainerFactory
.Create();
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
);
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
);
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
);
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
;
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
);
209 Marshal
.ReleaseComObject(scheduler
);
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
);
233 Marshal
.ReleaseComObject(scheduler
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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)]
481 get { return _valueType; }
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; }
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; }
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
559 public Lazy
<IDuck
> Duck
566 private class DuckImporter
576 public class QuackLikeADuck
578 public virtual string Quack()
584 public interface IDuck
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
605 private class ImportComComponent
607 [Import("TaskScheduler")]
608 public ITaskScheduler TaskScheduler
615 private class DelayImportComComponent
617 [Import("TaskScheduler")]
618 public Lazy
<ITaskScheduler
> TaskScheduler
627 public class Importer
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()
655 public int ValueReadWrite { get; set; }
658 public Lazy
<int> MetadataReadWrite { get; set; }
662 public class ImporterInvalidWrongType
665 public DateTime ValueReadWrite { get; set; }
669 public class ImporterInvalidSetterException
671 [ImportMany("Value")]
672 public IEnumerable
<int> ValueReadWrite { get { return null; }
set { throw new InvalidOperationException(); }
}
676 public class ImportImporterInvalidSetterExceptionLazily
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)
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)
711 public int Value { get; set; }
715 public class ExportsString
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>>();
734 public class ImportsListOfExportOfString
736 [Import(AllowDefault
= true)]
737 public List
<Lazy
<string>> ExportedList { get; set; }
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
);
753 public void ImportListOfExportWithInvalidCollectionAvailable_ShouldThrowMismatch()
755 var container
= ContainerFactory
.CreateWithAttributedCatalog(typeof(ExportsInvalidListOfExportOfString
), typeof(ImportsListOfExportOfString
));
757 CompositionAssert
.ThrowsError(ErrorId
.ImportEngine_PartCannotGetExportedValue
, () =>
758 container
.GetExportedValue
<ImportsListOfExportOfString
>());
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
);