1
// -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
5 using System
.Collections
.Generic
;
6 using System
.ComponentModel
.Composition
;
7 using System
.ComponentModel
.Composition
.Factories
;
8 using System
.ComponentModel
.Composition
.Hosting
;
9 using System
.ComponentModel
.Composition
.Primitives
;
10 using System
.ComponentModel
.Composition
.UnitTesting
;
12 using Microsoft
.VisualStudio
.TestTools
.UnitTesting
;
13 using System
.UnitTesting
;
14 using System
.Reflection
;
15 using System
.Collections
.ObjectModel
;
17 namespace System
.ComponentModel
.Composition
20 public class MetadataTests
22 #region Tests for metadata on exports
24 public enum SimpleEnum
31 [ExportMetadata("String", "42")]
32 [ExportMetadata("Int", 42)]
33 [ExportMetadata("Float", 42.0f
)]
34 [ExportMetadata("Enum", SimpleEnum
.First
)]
35 [ExportMetadata("Type", typeof(string))]
36 [ExportMetadata("Object", 42)]
37 public class SimpleMetadataExporter
43 [ExportMetadata("String", null)] // null
44 [ExportMetadata("Int", 42)]
45 [ExportMetadata("Float", 42.0f
)]
46 [ExportMetadata("Enum", SimpleEnum
.First
)]
47 [ExportMetadata("Type", typeof(string))]
48 [ExportMetadata("Object", 42)]
49 public class SimpleMetadataExporterWithNullReferenceValue
55 [ExportMetadata("String", "42")]
56 [ExportMetadata("Int", null)] //null
57 [ExportMetadata("Float", 42.0f
)]
58 [ExportMetadata("Enum", SimpleEnum
.First
)]
59 [ExportMetadata("Type", typeof(string))]
60 [ExportMetadata("Object", 42)]
61 public class SimpleMetadataExporterWithNullNonReferenceValue
67 [ExportMetadata("String", "42")]
68 [ExportMetadata("Int", "42")] // wrong type
69 [ExportMetadata("Float", 42.0f
)]
70 [ExportMetadata("Enum", SimpleEnum
.First
)]
71 [ExportMetadata("Type", typeof(string))]
72 [ExportMetadata("Object", 42)]
73 public class SimpleMetadataExporterWithTypeMismatch
77 public interface ISimpleMetadataView
79 string String { get; }
82 SimpleEnum Enum { get; }
84 object Object { get; }
88 public void SimpleMetadataTest()
90 var container
= ContainerFactory
.Create();
91 container
.ComposeParts(new SimpleMetadataExporter());
93 var export
= container
.GetExport
<SimpleMetadataExporter
, ISimpleMetadataView
>();
95 Assert
.AreEqual("42", export
.Metadata
.String
);
96 Assert
.AreEqual(42, export
.Metadata
.Int
);
97 Assert
.AreEqual(42.0f
, export
.Metadata
.Float
);
98 Assert
.AreEqual(SimpleEnum
.First
, export
.Metadata
.Enum
);
99 Assert
.AreEqual(typeof(string), export
.Metadata
.Type
);
100 Assert
.AreEqual(42, export
.Metadata
.Object
);
104 public void SimpleMetadataTestWithNullReferenceValue()
106 var container
= ContainerFactory
.Create();
107 container
.ComposeParts(new SimpleMetadataExporterWithNullReferenceValue());
109 var export
= container
.GetExport
<SimpleMetadataExporterWithNullReferenceValue
, ISimpleMetadataView
>();
111 Assert
.AreEqual(null, export
.Metadata
.String
);
112 Assert
.AreEqual(42, export
.Metadata
.Int
);
113 Assert
.AreEqual(42.0f
, export
.Metadata
.Float
);
114 Assert
.AreEqual(SimpleEnum
.First
, export
.Metadata
.Enum
);
115 Assert
.AreEqual(typeof(string), export
.Metadata
.Type
);
116 Assert
.AreEqual(42, export
.Metadata
.Object
);
120 public void SimpleMetadataTestWithNullNonReferenceValue()
122 var container
= ContainerFactory
.Create();
123 container
.ComposeParts(new SimpleMetadataExporterWithNullNonReferenceValue());
125 var exports
= container
.GetExports
<SimpleMetadataExporterWithNullNonReferenceValue
, ISimpleMetadataView
>();
126 Assert
.IsFalse(exports
.Any());
130 public void SimpleMetadataTestWithTypeMismatch()
132 var container
= ContainerFactory
.Create();
133 container
.ComposeParts(new SimpleMetadataExporterWithTypeMismatch());
135 var exports
= container
.GetExports
<SimpleMetadataExporterWithTypeMismatch
, ISimpleMetadataView
>();
136 Assert
.IsFalse(exports
.Any());
140 public void ValidMetadataTest()
142 var container
= ContainerFactory
.Create();
143 CompositionBatch batch
= new CompositionBatch();
144 batch
.AddPart(new MyExporterWithValidMetadata());
145 container
.Compose(batch
);
147 var typeVi
= container
.GetExport
<MyExporterWithValidMetadata
, IDictionary
<string, object>>();
148 var metadataFoo
= typeVi
.Metadata
["foo"] as IList
<string>;
149 Assert
.AreEqual(2, metadataFoo
.Count(), "There are should be two items in the metadata foo's collection");
150 Assert
.IsTrue(metadataFoo
.Contains("bar1"), "The metadata collection should include value 'bar1'");
151 Assert
.IsTrue(metadataFoo
.Contains("bar2"), "The metadata collection should include value 'bar2'");
152 Assert
.AreEqual("world", typeVi
.Metadata
["hello"], "The single item metadata should be present");
153 Assert
.AreEqual("GoodOneValue2", typeVi
.Metadata
["GoodOne2"], "The metadata supplied by strong attribute should also be present");
155 var metadataAcme
= typeVi
.Metadata
["acme"] as IList
<object>;
156 Assert
.AreEqual(2, metadataAcme
.Count(), "There are should be two items in the metadata acme's collection");
157 Assert
.IsTrue(metadataAcme
.Contains("acmebar"), "The metadata collection should include value 'bar'");
158 Assert
.IsTrue(metadataAcme
.Contains(2.0), "The metadata collection should include value 2");
160 var memberVi
= container
.GetExport
<Func
<double>, IDictionary
<string, object>>("ContractForValidMetadata");
161 var metadataBar
= memberVi
.Metadata
["bar"] as IList
<string>;
162 Assert
.AreEqual(2, metadataBar
.Count(), "There are should be two items in the metadata bar's collection");
163 Assert
.IsTrue(metadataBar
.Contains("foo1"), "The metadata collection should include value 'foo1'");
164 Assert
.IsTrue(metadataBar
.Contains("foo2"), "The metadata collection should include value 'foo2'");
165 Assert
.AreEqual("hello", memberVi
.Metadata
["world"], "The single item metadata should be present");
166 Assert
.AreEqual("GoodOneValue2", memberVi
.Metadata
["GoodOne2"], "The metadata supplied by strong attribute should also be present");
168 var metadataStuff
= memberVi
.Metadata
["stuff"] as IList
<object>;
169 Assert
.AreEqual(2, metadataAcme
.Count(), "There are should be two items in the metadata acme's collection");
170 Assert
.IsTrue(metadataStuff
.Contains("acmebar"), "The metadata collection should include value 'acmebar'");
171 Assert
.IsTrue(metadataStuff
.Contains(2.0), "The metadata collection should include value 2");
176 public void ValidMetadataDiscoveredByComponentCatalogTest()
178 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
179 ValidMetadataDiscoveredByCatalog(container
);
182 private void ValidMetadataDiscoveredByCatalog(CompositionContainer container
)
184 var export1
= container
.GetExport
<MyExporterWithValidMetadata
, IDictionary
<string, object>>();
186 var metadataFoo
= export1
.Metadata
["foo"] as IList
<string>;
187 Assert
.AreEqual(2, metadataFoo
.Count(), "There are should be two items in the metadata foo's collection");
188 Assert
.IsTrue(metadataFoo
.Contains("bar1"), "The metadata collection should include value 'bar1'");
189 Assert
.IsTrue(metadataFoo
.Contains("bar2"), "The metadata collection should include value 'bar2'");
190 Assert
.AreEqual("world", export1
.Metadata
["hello"], "The single item metadata should also be present");
191 Assert
.AreEqual("GoodOneValue2", export1
.Metadata
["GoodOne2"], "The metadata supplied by strong attribute should also be present");
193 var metadataAcme
= export1
.Metadata
["acme"] as IList
<object>;
194 Assert
.AreEqual(2, metadataAcme
.Count(), "There are should be two items in the metadata acme's collection");
195 Assert
.IsTrue(metadataAcme
.Contains("acmebar"), "The metadata collection should include value 'bar'");
196 Assert
.IsTrue(metadataAcme
.Contains(2.0), "The metadata collection should include value 2");
198 var export2
= container
.GetExport
<Func
<double>, IDictionary
<string, object>>("ContractForValidMetadata");
199 var metadataBar
= export2
.Metadata
["bar"] as IList
<string>;
200 Assert
.AreEqual(2, metadataBar
.Count(), "There are should be two items in the metadata foo's collection");
201 Assert
.IsTrue(metadataBar
.Contains("foo1"), "The metadata collection should include value 'foo1'");
202 Assert
.IsTrue(metadataBar
.Contains("foo2"), "The metadata collection should include value 'foo2'");
203 Assert
.AreEqual("hello", export2
.Metadata
["world"], "The single item metadata should also be present");
204 Assert
.AreEqual("GoodOneValue2", export2
.Metadata
["GoodOne2"], "The metadata supplied by strong attribute should also be present");
206 var metadataStuff
= export2
.Metadata
["stuff"] as IList
<object>;
207 Assert
.AreEqual(2, metadataAcme
.Count(), "There are should be two items in the metadata acme's collection");
208 Assert
.IsTrue(metadataStuff
.Contains("acmebar"), "The metadata collection should include value 'acmebar'");
209 Assert
.IsTrue(metadataStuff
.Contains(2.0), "The metadata collection should include value 2");
213 [AttributeUsage(AttributeTargets
.All
, AllowMultiple
= true)]
215 public class BadStrongMetadata
: Attribute
217 public string SelfConflicted { get { return "SelfConflictedValue"; }
}
222 [ExportMetadata("InvalidCollection", "InvalidCollectionValue1")]
223 [ExportMetadata("InvalidCollection", "InvalidCollectionValue2", IsMultiple
= true)]
225 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue1")]
226 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue2")]
227 [ExportMetadata("GoodOne1", "GoodOneValue1")]
228 [ExportMetadata("ConflictedOne1", "ConfilictedOneValue1")]
230 [ExportMetadata("ConflictedOne2", "ConflictedOne2Value2")]
231 [PartNotDiscoverable
]
232 public class MyExporterWithInvalidMetadata
234 [Export("ContractForInvalidMetadata")]
235 [ExportMetadata("ConflictedOne1", "ConfilictedOneValue1")]
237 [ExportMetadata("ConflictedOne2", "ConflictedOne2Value2")]
238 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue1")]
239 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue2")]
241 [ExportMetadata("InvalidCollection", "InvalidCollectionValue1")]
242 [ExportMetadata("InvalidCollection", "InvalidCollectionValue2", IsMultiple
= true)]
244 [ExportMetadata("GoodOne1", "GoodOneValue1")]
245 public double DoSomething() { return 0.618; }
249 [ExportMetadata("DuplicateMetadataName", "My Name")]
250 [ExportMetadata("DuplicateMetadataName", "Your Name")]
251 [PartNotDiscoverable
]
252 public class ClassWithInvalidDuplicateMetadataOnType
258 public void InvalidDuplicateMetadataOnType_ShouldThrow()
260 var part
= AttributedModelServices
.CreatePart(new ClassWithInvalidDuplicateMetadataOnType());
261 var export
= part
.ExportDefinitions
.First();
262 var ex
= ExceptionAssert
.Throws
<InvalidOperationException
>(RetryMode
.DoNotRetry
, () =>
264 var metadata
= export
.Metadata
;
267 Assert
.IsTrue(ex
.Message
.Contains("DuplicateMetadataName"));
270 [PartNotDiscoverable
]
271 public class ClassWithInvalidDuplicateMetadataOnMember
274 [ExportMetadata("DuplicateMetadataName", "My Name")]
275 [ExportMetadata("DuplicateMetadataName", "Your Name")]
276 public ClassWithDuplicateMetadataOnMember Member { get; set; }
280 public void InvalidDuplicateMetadataOnMember_ShouldThrow()
282 var part
= AttributedModelServices
.CreatePart(new ClassWithInvalidDuplicateMetadataOnMember());
283 var export
= part
.ExportDefinitions
.First();
285 var ex
= ExceptionAssert
.Throws
<InvalidOperationException
>(RetryMode
.DoNotRetry
, () =>
287 var metadata
= export
.Metadata
;
290 Assert
.IsTrue(ex
.Message
.Contains("DuplicateMetadataName"));
294 [ExportMetadata("DuplicateMetadataName", "My Name", IsMultiple
=true)]
295 [ExportMetadata("DuplicateMetadataName", "Your Name", IsMultiple
=true)]
296 public class ClassWithValidDuplicateMetadataOnType
302 public void ValidDuplicateMetadataOnType_ShouldDiscoverAllMetadata()
304 var container
= ContainerFactory
.Create();
305 CompositionBatch batch
= new CompositionBatch();
306 batch
.AddPart(new ClassWithValidDuplicateMetadataOnType());
308 container
.Compose(batch
);
310 var export
= container
.GetExport
<ClassWithValidDuplicateMetadataOnType
, IDictionary
<string, object>>();
312 var names
= export
.Metadata
["DuplicateMetadataName"] as string[];
314 Assert
.AreEqual(2, names
.Length
);
317 public class ClassWithDuplicateMetadataOnMember
320 [ExportMetadata("DuplicateMetadataName", "My Name", IsMultiple
=true)]
321 [ExportMetadata("DuplicateMetadataName", "Your Name", IsMultiple
=true)]
322 public ClassWithDuplicateMetadataOnMember Member { get; set; }
326 public void ValidDuplicateMetadataOnMember_ShouldDiscoverAllMetadata()
328 var container
= ContainerFactory
.Create();
329 CompositionBatch batch
= new CompositionBatch();
330 batch
.AddPart(new ClassWithDuplicateMetadataOnMember());
332 container
.Compose(batch
);
334 var export
= container
.GetExport
<ClassWithDuplicateMetadataOnMember
, IDictionary
<string, object>>();
336 var names
= export
.Metadata
["DuplicateMetadataName"] as string[];
338 Assert
.AreEqual(2, names
.Length
);
342 [ExportMetadata(CompositionConstants
.PartCreationPolicyMetadataName
, "My Policy")]
343 [PartNotDiscoverable
]
344 public class ClassWithReservedMetadataValue
350 public void InvalidMetadata_UseOfReservedName_ShouldThrow()
352 var part
= AttributedModelServices
.CreatePart(new ClassWithReservedMetadataValue());
353 var export
= part
.ExportDefinitions
.First();
355 var ex
= ExceptionAssert
.Throws
<InvalidOperationException
>(RetryMode
.DoNotRetry
, () =>
357 var metadata
= export
.Metadata
;
360 Assert
.IsTrue(ex
.Message
.Contains(CompositionConstants
.PartCreationPolicyMetadataName
));
365 #region Tests for weakly supported metadata as part of contract
370 public void FailureImportForNoRequiredMetadatForExportCollection()
372 CompositionContainer container
= ContainerFactory
.Create();
374 MyImporterWithExportCollection importer
;
375 CompositionBatch batch
= new CompositionBatch();
376 batch
.AddPart(new MyExporterWithNoMetadata());
377 batch
.AddPart(importer
= new MyImporterWithExportCollection());
381 //var result = container.TryCompose();
383 //Assert.IsTrue(result.Succeeded, "Composition should be successful because collection import is not required");
384 //Assert.AreEqual(1, result.Issues.Count, "There should be one issue reported");
385 //Assert.IsTrue(result.Issues[0].Description.Contains("Foo"), "The missing required metadata is 'Foo'");
391 public void FailureImportForNoRequiredMetadataThroughComponentCatalogTest()
393 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
394 FailureImportForNoRequiredMetadataThroughCatalog(container
);
397 private void FailureImportForNoRequiredMetadataThroughCatalog(CompositionContainer container
)
399 Assert
.Fail("This needs to be fixed, see: 472538");
401 //var export1 = container.GetExport<MyImporterWithExport>();
403 //export1.TryGetExportedValue().VerifyFailure(CompositionIssueId.RequiredMetadataNotFound, CompositionIssueId.CardinalityMismatch);
405 //var export2 = container.GetExport<MyImporterWithExportCollection>();
406 //export2.TryGetExportedValue().VerifySuccess(CompositionIssueId.RequiredMetadataNotFound);
408 //container.TryGetExportedValue<MyImporterWithValue>().VerifyFailure(CompositionIssueId.RequiredMetadataNotFound, CompositionIssueId.CardinalityMismatch);
414 public void SelectiveImportBasedOnMetadataForExport()
416 CompositionContainer container
= ContainerFactory
.Create();
418 MyImporterWithExportForSelectiveImport importer
;
419 CompositionBatch batch
= new CompositionBatch();
420 batch
.AddPart(new MyExporterWithNoMetadata());
421 batch
.AddPart(new MyExporterWithMetadata());
422 batch
.AddPart(importer
= new MyImporterWithExportForSelectiveImport());
425 //var result = container.TryCompose();
427 //Assert.IsTrue(result.Succeeded, "Composition should be successfull because one of two exports meets both the contract name and metadata requirement");
428 //Assert.AreEqual(1, result.Issues.Count, "There should be one issue reported about the export who has no required metadata");
429 //Assert.IsTrue(result.Issues[0].Description.Contains("Foo"), "The missing required metadata is 'Foo'");
430 //Assert.IsNotNull(importer.ValueInfo, "The import should really get bound");
436 public void SelectiveImportBasedOnMetadataForExportCollection()
438 CompositionContainer container
= ContainerFactory
.Create();
440 MyImporterWithExportCollectionForSelectiveImport importer
;
441 CompositionBatch batch
= new CompositionBatch();
442 batch
.AddPart(new MyExporterWithNoMetadata());
443 batch
.AddPart(new MyExporterWithMetadata());
444 batch
.AddPart(importer
= new MyImporterWithExportCollectionForSelectiveImport());
448 //var result = container.TryCompose();
450 //Assert.IsTrue(result.Succeeded, "Composition should be successfull in anyway for collection import");
451 //Assert.AreEqual(1, result.Issues.Count, "There should be one issue reported however, about the export who has no required metadata");
452 //Assert.IsTrue(result.Issues[0].Description.Contains("Foo"), "The missing required metadata is 'Foo'");
453 //Assert.AreEqual(1, importer.ValueInfoCol.Count, "The export with required metadata should get bound");
454 //Assert.IsNotNull(importer.ValueInfoCol[0], "The import should really get bound");
461 public void SelectiveImportBasedOnMetadataThruoughComponentCatalogTest()
463 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
464 SelectiveImportBasedOnMetadataThruoughCatalog(container
);
467 private void SelectiveImportBasedOnMetadataThruoughCatalog(CompositionContainer container
)
469 Assert
.Fail("This needs to be fixed, see: 472538");
471 //var export1 = container.GetExport<MyImporterWithExportForSelectiveImport>();
472 //export1.TryGetExportedValue().VerifySuccess(CompositionIssueId.RequiredMetadataNotFound);
474 //var export2 = container.GetExport<MyImporterWithExportCollectionForSelectiveImport>();
475 //export2.TryGetExportedValue().VerifySuccess(CompositionIssueId.RequiredMetadataNotFound);
479 public void ChildParentContainerTest1()
481 CompositionContainer parent
= ContainerFactory
.Create();
482 CompositionContainer child
= new CompositionContainer(parent
);
484 CompositionBatch childBatch
= new CompositionBatch();
485 CompositionBatch parentBatch
= new CompositionBatch();
486 parentBatch
.AddPart(new MyExporterWithNoMetadata());
487 childBatch
.AddPart(new MyExporterWithMetadata());
488 parent
.Compose(parentBatch
);
489 child
.Compose(childBatch
);
491 var exports
= child
.GetExports(CreateImportDefinition(typeof(IMyExporter
), "Foo"));
493 Assert
.AreEqual(1, exports
.Count());
497 public void ChildParentContainerTest2()
499 CompositionContainer parent
= ContainerFactory
.Create();
500 CompositionContainer child
= new CompositionContainer(parent
);
502 CompositionBatch childBatch
= new CompositionBatch();
503 CompositionBatch parentBatch
= new CompositionBatch();
504 parentBatch
.AddPart(new MyExporterWithMetadata());
505 childBatch
.AddPart(new MyExporterWithNoMetadata());
506 parent
.Compose(parentBatch
);
508 var exports
= child
.GetExports(CreateImportDefinition(typeof(IMyExporter
), "Foo"));
510 Assert
.AreEqual(1, exports
.Count());
514 public void ChildParentContainerTest3()
516 CompositionContainer parent
= ContainerFactory
.Create();
517 CompositionContainer child
= new CompositionContainer(parent
);
519 CompositionBatch childBatch
= new CompositionBatch();
520 CompositionBatch parentBatch
= new CompositionBatch();
522 parentBatch
.AddPart(new MyExporterWithMetadata());
523 childBatch
.AddPart(new MyExporterWithMetadata());
524 parent
.Compose(parentBatch
);
525 child
.Compose(childBatch
);
527 var exports
= child
.GetExports(CreateImportDefinition(typeof(IMyExporter
), "Foo"));
529 Assert
.AreEqual(2, exports
.Count(), "There should be two from child and parent container each");
532 private static ImportDefinition
CreateImportDefinition(Type type
, string metadataKey
)
534 return new ContractBasedImportDefinition(AttributedModelServices
.GetContractName(typeof(IMyExporter
)), null, new KeyValuePair
<string, Type
>[] { new KeyValuePair<string, Type>(metadataKey, typeof(object))}
, ImportCardinality
.ZeroOrMore
, true, true, CreationPolicy
.Any
);
539 #region Tests for strongly typed metadata as part of contract
544 public void SelectiveImportBySTM_Export()
546 CompositionContainer container
= ContainerFactory
.Create();
547 CompositionBatch batch
= new CompositionBatch();
549 MyImporterWithExportStronglyTypedMetadata importer
;
550 batch
.AddPart(new MyExporterWithNoMetadata());
551 batch
.AddPart(new MyExporterWithMetadata());
552 batch
.AddPart(importer
= new MyImporterWithExportStronglyTypedMetadata());
556 //var result = container.TryCompose();
558 //Assert.IsTrue(result.Succeeded, "Composition should be successful becasue one of two exports does not have required metadata");
559 //Assert.AreEqual(1, result.Issues.Count, "There should be an issue reported about the export who has no required metadata");
560 //Assert.IsNotNull(importer.ValueInfo, "The valid export should really get bound");
561 //Assert.AreEqual("Bar", importer.ValueInfo.Metadata.Foo, "The value of metadata 'Foo' should be 'Bar'");
567 public void SelectiveImportBySTM_ExportCollection()
569 CompositionContainer container
= ContainerFactory
.Create();
571 MyImporterWithExportCollectionStronglyTypedMetadata importer
;
572 CompositionBatch batch
= new CompositionBatch();
574 batch
.AddPart(new MyExporterWithNoMetadata());
575 batch
.AddPart(new MyExporterWithMetadata());
576 batch
.AddPart(importer
= new MyImporterWithExportCollectionStronglyTypedMetadata());
580 //var result = container.TryCompose();
582 //Assert.IsTrue(result.Succeeded, "Collection import should be successful in anyway");
583 //Assert.AreEqual(1, result.Issues.Count, "There should be an issue reported about the export with no required metadata");
584 //Assert.AreEqual(1, importer.ValueInfoCol.Count, "There should be only one export got bound");
585 //Assert.AreEqual("Bar", importer.ValueInfoCol.First().Metadata.Foo, "The value of metadata 'Foo' should be 'Bar'");
589 public void SelectiveImportBySTMThroughComponentCatalog1()
591 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
592 SelectiveImportBySTMThroughCatalog1(container
);
595 public void SelectiveImportBySTMThroughCatalog1(CompositionContainer container
)
597 Assert
.IsNotNull(container
.GetExport
<IMyExporter
, IMetadataView
>());
599 var result2
= container
.GetExports
<IMyExporter
, IMetadataView
>();
605 public void SelectiveImportBySTMThroughComponentCatalog2()
607 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
608 SelectiveImportBySTMThroughCatalog2(container
);
611 public void SelectiveImportBySTMThroughCatalog2(CompositionContainer container
)
613 Assert
.Fail("This needs to be fixed, see: 472538");
615 //var export1 = container.GetExport<MyImporterWithExportStronglyTypedMetadata>();
616 //var result1 = export1.TryGetExportedValue().VerifySuccess(CompositionIssueId.RequiredMetadataNotFound);
617 //Assert.IsNotNull(result1.Value.ValueInfo, "The valid export should really get bound");
618 //Assert.AreEqual("Bar", result1.Value.ValueInfo.Metadata.Foo, "The value of metadata 'Foo' should be 'Bar'");
620 //var export2 = container.GetExport<MyImporterWithExportCollectionStronglyTypedMetadata>();
621 //var result2 = export2.TryGetExportedValue().VerifySuccess(CompositionIssueId.RequiredMetadataNotFound);
622 //Assert.AreEqual(1, result2.Value.ValueInfoCol.Count, "There should be only one export got bound");
623 //Assert.AreEqual("Bar", result2.Value.ValueInfoCol.First().Metadata.Foo, "The value of metadata 'Foo' should be 'Bar'");
627 public void TestMultipleStronglyTypedAttributes()
629 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
631 var export
= container
.GetExport
<ExportMultiple
, IMyOptions
>();
632 EnumerableAssert
.AreEqual(export
.Metadata
.OptionNames
.OrderBy(s
=> s
), "name1", "name2", "name3");
633 EnumerableAssert
.AreEqual(export
.Metadata
.OptionValues
.OrderBy(o
=> o
.ToString()), "value1", "value2", "value3");
637 public void TestMultipleStronglyTypedAttributesAsIEnumerable()
639 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
641 var export
= container
.GetExport
<ExportMultiple
, IMyOptionsAsIEnumerable
>();
642 EnumerableAssert
.AreEqual(export
.Metadata
.OptionNames
.OrderBy(s
=> s
), "name1", "name2", "name3");
643 EnumerableAssert
.AreEqual(export
.Metadata
.OptionValues
.OrderBy(o
=> o
.ToString()), "value1", "value2", "value3");
647 public void TestMultipleStronglyTypedAttributesAsArray()
649 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
651 var export
= container
.GetExport
<ExportMultiple
, IMyOptionsAsArray
>();
652 EnumerableAssert
.AreEqual(export
.Metadata
.OptionNames
.OrderBy(s
=> s
), "name1", "name2", "name3");
653 EnumerableAssert
.AreEqual(export
.Metadata
.OptionValues
.OrderBy(o
=> o
.ToString()), "value1", "value2", "value3");
657 public void TestMultipleStronglyTypedAttributesWithInvalidType()
659 var container
= ContainerFactory
.CreateWithDefaultAttributedCatalog();
661 // IMyOption2 actually contains all the correct properties but just the wrong types. This should cause us to not match the exports by metadata
662 var exports
= container
.GetExports
<ExportMultiple
, IMyOption2
>();
663 Assert
.AreEqual(0, exports
.Count());
667 public void TestOptionalMetadataValueTypeMismatch()
669 var container
= ContainerFactory
.CreateWithAttributedCatalog(typeof(OptionalFooIsInt
));
670 var exports
= container
.GetExports
<OptionalFooIsInt
, IMetadataView
>();
671 Assert
.AreEqual(1, exports
.Count());
672 var export
= exports
.Single();
673 Assert
.AreEqual(null, export
.Metadata
.OptionalFoo
);
679 [ExportMetadata("Name", "FromBaseType")]
680 public abstract class BaseClassWithMetadataButNoExport
684 [Export(typeof(BaseClassWithMetadataButNoExport
))]
685 public class DerivedClassWithExportButNoMetadata
: BaseClassWithMetadataButNoExport
690 public void Metadata_BaseClassWithMetadataButNoExport()
692 var container
= ContainerFactory
.CreateWithAttributedCatalog(
693 typeof(BaseClassWithMetadataButNoExport
),
694 typeof(DerivedClassWithExportButNoMetadata
));
696 var export
= container
.GetExport
<BaseClassWithMetadataButNoExport
, IDictionary
<string, object>>();
698 Assert
.IsFalse(export
.Metadata
.ContainsKey("Name"), "Export should only contain metadata from the derived!");
701 [InheritedExport(typeof(BaseClassWithExportButNoMetadata
))]
702 public abstract class BaseClassWithExportButNoMetadata
707 [ExportMetadata("Name", "FromDerivedType")]
708 public class DerivedClassMetadataButNoExport
: BaseClassWithExportButNoMetadata
713 public void Metadata_BaseClassWithExportButNoMetadata()
715 var container
= ContainerFactory
.CreateWithAttributedCatalog(
716 typeof(BaseClassWithExportButNoMetadata
),
717 typeof(DerivedClassMetadataButNoExport
));
719 var export
= container
.GetExport
<BaseClassWithExportButNoMetadata
, IDictionary
<string, object>>();
721 Assert
.IsFalse(export
.Metadata
.ContainsKey("Name"), "Export should only contain metadata from the base!");
724 [Export(typeof(BaseClassWithExportAndMetadata
))]
725 [ExportMetadata("Name", "FromBaseType")]
726 public class BaseClassWithExportAndMetadata
730 [Export(typeof(DerivedClassWithExportAndMetadata
))]
731 [ExportMetadata("Name", "FromDerivedType")]
732 public class DerivedClassWithExportAndMetadata
: BaseClassWithExportAndMetadata
737 public void Metadata_BaseAndDerivedWithExportAndMetadata()
739 var container
= ContainerFactory
.CreateWithAttributedCatalog(
740 typeof(BaseClassWithExportAndMetadata
),
741 typeof(DerivedClassWithExportAndMetadata
));
743 var exportBase
= container
.GetExport
<BaseClassWithExportAndMetadata
, IDictionary
<string, object>>();
745 Assert
.AreEqual("FromBaseType", exportBase
.Metadata
["Name"]);
747 var exportDerived
= container
.GetExport
<DerivedClassWithExportAndMetadata
, IDictionary
<string, object>>();
748 Assert
.AreEqual("FromDerivedType", exportDerived
.Metadata
["Name"]);
752 [ExportMetadata("Data", null, IsMultiple
=true)]
753 [ExportMetadata("Data", false, IsMultiple
=true)]
754 [ExportMetadata("Data", Int16
.MaxValue
, IsMultiple
= true)]
755 [ExportMetadata("Data", Int32
.MaxValue
, IsMultiple
= true)]
756 [ExportMetadata("Data", Int64
.MaxValue
, IsMultiple
= true)]
757 [ExportMetadata("Data", UInt16
.MaxValue
, IsMultiple
= true)]
758 [ExportMetadata("Data", UInt32
.MaxValue
, IsMultiple
= true)]
759 [ExportMetadata("Data", UInt64
.MaxValue
, IsMultiple
= true)]
760 [ExportMetadata("Data", "String", IsMultiple
= true)]
761 [ExportMetadata("Data", typeof(ClassWithLotsOfDifferentMetadataTypes
), IsMultiple
= true)]
762 [ExportMetadata("Data", CreationPolicy
.NonShared
, IsMultiple
=true)]
763 [ExportMetadata("Data", new object[] { 1, 2, null }
, IsMultiple
=true)]
764 [CLSCompliant(false)]
765 public class ClassWithLotsOfDifferentMetadataTypes
770 public void ExportWithValidCollectionOfMetadata_ShouldDiscoverAllMetadata()
772 var catalog
= CatalogFactory
.CreateAttributed(typeof(ClassWithLotsOfDifferentMetadataTypes
));
774 var export
= catalog
.Parts
.First().ExportDefinitions
.First();
776 var data
= (object[])export
.Metadata
["Data"];
778 Assert
.AreEqual(12, data
.Length
);
782 [ExportMetadata("Data", null, IsMultiple
= true)]
783 [ExportMetadata("Data", 1, IsMultiple
= true)]
784 [ExportMetadata("Data", 2, IsMultiple
= true)]
785 [ExportMetadata("Data", 3, IsMultiple
= true)]
786 public class ClassWithIntCollectionWithNullValue
791 public void ExportWithIntCollectionPlusNullValueOfMetadata_ShouldDiscoverAllMetadata()
793 var catalog
= CatalogFactory
.CreateAttributed(typeof(ClassWithIntCollectionWithNullValue
));
795 var export
= catalog
.Parts
.First().ExportDefinitions
.First();
797 var data
= (object[])export
.Metadata
["Data"];
799 Assert
.IsNotInstanceOfType(data
, typeof(int[]));
801 Assert
.AreEqual(4, data
.Length
);
804 [AttributeUsage(AttributeTargets
.Class
, AllowMultiple
=true)]
806 public class DataAttribute
: Attribute
808 public object Object { get; set; }
813 [Data(Object
= "10")]
814 public class ExportWithMultipleMetadata_ExportStringsAsObjects
819 [Data(Object
= "42")]
820 [Data(Object
= "10")]
821 [Data(Object
= null)]
822 public class ExportWithMultipleMetadata_ExportStringsAsObjects_WithNull
829 public class ExportWithMultipleMetadata_ExportIntsAsObjects
834 [Data(Object
= null)]
837 public class ExportWithMultipleMetadata_ExportIntsAsObjects_WithNull
841 public interface IObjectView_AsStrings
843 string[] Object { get; }
846 public interface IObjectView_AsInts
848 int[] Object { get; }
851 public interface IObjectView
853 object[] Object { get; }
858 public void ExportWithMultipleMetadata_ExportStringsAsObjects_ShouldDiscoverMetadataAsStrings()
860 var container
= ContainerFactory
.Create();
861 container
.ComposeParts(new ExportWithMultipleMetadata_ExportStringsAsObjects());
863 var export
= container
.GetExport
<ExportWithMultipleMetadata_ExportStringsAsObjects
, IObjectView_AsStrings
>();
864 Assert
.IsNotNull(export
);
866 Assert
.IsNotNull(export
.Metadata
);
867 Assert
.IsNotNull(export
.Metadata
.Object
);
868 Assert
.AreEqual(2, export
.Metadata
.Object
.Length
);
872 public void ExportWithMultipleMetadata_ExportStringsAsObjects_With_Null_ShouldDiscoverMetadataAsStrings()
874 var container
= ContainerFactory
.Create();
875 container
.ComposeParts(new ExportWithMultipleMetadata_ExportStringsAsObjects_WithNull());
877 var export
= container
.GetExport
<ExportWithMultipleMetadata_ExportStringsAsObjects_WithNull
, IObjectView_AsStrings
>();
878 Assert
.IsNotNull(export
);
880 Assert
.IsNotNull(export
.Metadata
);
881 Assert
.IsNotNull(export
.Metadata
.Object
);
882 Assert
.AreEqual(3, export
.Metadata
.Object
.Length
);
886 public void ExportWithMultipleMetadata_ExportIntsAsObjects_ShouldDiscoverMetadataAsInts()
888 var container
= ContainerFactory
.Create();
889 container
.ComposeParts(new ExportWithMultipleMetadata_ExportIntsAsObjects());
891 var export
= container
.GetExport
<ExportWithMultipleMetadata_ExportIntsAsObjects
, IObjectView_AsInts
>();
892 Assert
.IsNotNull(export
);
894 Assert
.IsNotNull(export
.Metadata
);
895 Assert
.IsNotNull(export
.Metadata
.Object
);
896 Assert
.AreEqual(2, export
.Metadata
.Object
.Length
);
900 public void ExportWithMultipleMetadata_ExportIntsAsObjects_With_Null_ShouldDiscoverMetadataAsObjects()
902 var container
= ContainerFactory
.Create();
903 container
.ComposeParts(new ExportWithMultipleMetadata_ExportIntsAsObjects_WithNull());
905 var exports
= container
.GetExports
<ExportWithMultipleMetadata_ExportIntsAsObjects_WithNull
, IObjectView_AsInts
>();
906 Assert
.IsFalse(exports
.Any());
908 var export
= container
.GetExport
<ExportWithMultipleMetadata_ExportIntsAsObjects_WithNull
, IObjectView
>();
910 Assert
.IsNotNull(export
.Metadata
);
911 Assert
.IsNotNull(export
.Metadata
.Object
);
912 Assert
.AreEqual(3, export
.Metadata
.Object
.Length
);
916 [AttributeUsage(AttributeTargets
.Class
, AllowMultiple
= true)]
917 public class OrderAttribute
: Attribute
919 public string Before { get; set; }
920 public string After { get; set; }
923 public interface IOrderMetadataView
925 string[] Before { get; }
926 string[] After { get; }
930 [Order(Before
= "Step3")]
931 [Order(Before
= "Step2")]
932 public class OrderedItemBeforesOnly
937 public void ExportWithMultipleMetadata_ExportStringsAndNulls_ThroughMetadataAttributes()
939 var container
= ContainerFactory
.Create();
940 container
.ComposeParts(new OrderedItemBeforesOnly());
942 var export
= container
.GetExport
<OrderedItemBeforesOnly
, IOrderMetadataView
>();
943 Assert
.IsNotNull(export
);
945 Assert
.IsNotNull(export
.Metadata
);
947 Assert
.IsNotNull(export
.Metadata
.Before
);
948 Assert
.IsNotNull(export
.Metadata
.After
);
950 Assert
.AreEqual(2, export
.Metadata
.Before
.Length
);
951 Assert
.AreEqual(2, export
.Metadata
.After
.Length
);
953 Assert
.IsNotNull(export
.Metadata
.Before
[0]);
954 Assert
.IsNotNull(export
.Metadata
.Before
[1]);
956 Assert
.IsNull(export
.Metadata
.After
[0]);
957 Assert
.IsNull(export
.Metadata
.After
[1]);
961 [AttributeUsage(AttributeTargets
.Class
, AllowMultiple
= true)]
962 public class DataTypeAttribute
: Attribute
964 public Type Type { get; set; }
967 public interface ITypesMetadataView
973 [DataType(Type
= typeof(int))]
974 [DataType(Type
= typeof(string))]
975 public class ItemWithTypeExports
980 [DataType(Type
= typeof(int))]
981 [DataType(Type
= typeof(string))]
982 [DataType(Type
= null)]
983 public class ItemWithTypeExports_WithNulls
988 [DataType(Type
= null)]
989 [DataType(Type
= null)]
990 [DataType(Type
= null)]
991 public class ItemWithTypeExports_WithAllNulls
996 public void ExportWithMultipleMetadata_ExportTypes()
998 var container
= ContainerFactory
.Create();
999 container
.ComposeParts(new ItemWithTypeExports());
1001 var export
= container
.GetExport
<ItemWithTypeExports
, ITypesMetadataView
>();
1003 Assert
.IsNotNull(export
.Metadata
);
1004 Assert
.IsNotNull(export
.Metadata
.Type
);
1005 Assert
.AreEqual(2, export
.Metadata
.Type
.Length
);
1009 public void ExportWithMultipleMetadata_ExportTypes_WithNulls()
1011 var container
= ContainerFactory
.Create();
1012 container
.ComposeParts(new ItemWithTypeExports_WithNulls());
1014 var export
= container
.GetExport
<ItemWithTypeExports_WithNulls
, ITypesMetadataView
>();
1016 Assert
.IsNotNull(export
.Metadata
);
1017 Assert
.IsNotNull(export
.Metadata
.Type
);
1018 Assert
.AreEqual(3, export
.Metadata
.Type
.Length
);
1022 public void ExportWithMultipleMetadata_ExportTypes_WithAllNulls()
1024 var container
= ContainerFactory
.Create();
1025 container
.ComposeParts(new ItemWithTypeExports_WithAllNulls());
1027 var export
= container
.GetExport
<ItemWithTypeExports_WithAllNulls
, ITypesMetadataView
>();
1029 Assert
.IsNotNull(export
.Metadata
);
1030 Assert
.IsNotNull(export
.Metadata
.Type
);
1031 Assert
.AreEqual(3, export
.Metadata
.Type
.Length
);
1033 Assert
.IsNull(export
.Metadata
.Type
[0]);
1034 Assert
.IsNull(export
.Metadata
.Type
[1]);
1035 Assert
.IsNull(export
.Metadata
.Type
[2]);
1038 [ExportMetadata(null, "ValueOfNullKey")]
1039 public class ClassWithNullMetadataKey
1044 public void ExportMetadataWithNullKey_ShouldUseEmptyString()
1046 var nullMetadataCatalog
= CatalogFactory
.CreateAttributed(typeof(ClassWithNullMetadataKey
));
1047 var nullMetadataExport
= nullMetadataCatalog
.Parts
.Single().ExportDefinitions
.Single();
1049 Assert
.IsTrue(nullMetadataExport
.Metadata
.ContainsKey(string.Empty
));
1050 Assert
.AreEqual("ValueOfNullKey", nullMetadataExport
.Metadata
[string.Empty
]);
1059 // Tests for metadata issues on export
1062 [ExportMetadata("foo", "bar1", IsMultiple
= true)]
1063 [ExportMetadata("foo", "bar2", IsMultiple
= true)]
1064 [ExportMetadata("acme", "acmebar", IsMultiple
= true)]
1065 [ExportMetadata("acme", 2.0, IsMultiple
= true)]
1066 [ExportMetadata("hello", "world")]
1067 [GoodStrongMetadata
]
1068 public class MyExporterWithValidMetadata
1070 [Export("ContractForValidMetadata")]
1071 [ExportMetadata("bar", "foo1", IsMultiple
= true)]
1072 [ExportMetadata("bar", "foo2", IsMultiple
= true)]
1073 [ExportMetadata("stuff", "acmebar", IsMultiple
= true)]
1074 [ExportMetadata("stuff", 2.0, IsMultiple
= true)]
1075 [ExportMetadata("world", "hello")] // the order of the attribute should not affect the result
1076 [GoodStrongMetadata
]
1077 public double DoSomething() { return 0.618; }
1080 [AttributeUsage(AttributeTargets
.All
, AllowMultiple
= false)]
1082 public class GoodStrongMetadata
: Attribute
1084 public string GoodOne2 { get { return "GoodOneValue2"; }
}
1085 public string ConflictedOne1 { get { return "ConflictedOneValue1"; }
}
1086 public string ConflictedOne2 { get { return "ConflictedOneValue2"; }
}
1089 // Tests for metadata as part of contract
1091 public interface IMyExporter { }
1094 [Export(typeof(IMyExporter
))]
1095 public class MyExporterWithNoMetadata
: IMyExporter
1100 [Export(typeof(IMyExporter
))]
1101 [ExportMetadata("Foo", "Bar")]
1102 public class MyExporterWithMetadata
: IMyExporter
1107 public interface IMetadataFoo
1112 public interface IMetadataBar
1118 public class MyImporterWithExport
1120 [Import(typeof(MyExporterWithNoMetadata
))]
1121 public Lazy
<MyExporterWithNoMetadata
, IMetadataFoo
> ValueInfo { get; set; }
1125 public class SingleImportWithAllowDefault
1127 [Import("Import", AllowDefault
= true)]
1128 public Lazy
<object> Import { get; set; }
1132 public class SingleImport
1135 public Lazy
<object> Import { get; set; }
1138 public interface IFooMetadataView
1144 public class MyImporterWithExportCollection
1146 [ImportMany(typeof(MyExporterWithNoMetadata
))]
1147 public IEnumerable
<Lazy
<MyExporterWithNoMetadata
, IFooMetadataView
>> ValueInfoCol { get; set; }
1151 public class MyImporterWithExportForSelectiveImport
1154 public Lazy
<IMyExporter
, IFooMetadataView
> ValueInfo { get; set; }
1158 public class MyImporterWithExportCollectionForSelectiveImport
1161 public Collection
<Lazy
<IMyExporter
, IFooMetadataView
>> ValueInfoCol { get; set; }
1164 public interface IMetadataView
1168 [System
.ComponentModel
.DefaultValue(null)]
1169 string OptionalFoo { get; }
1173 [ExportMetadata("Foo", "fooValue3")]
1174 [ExportMetadata("OptionalFoo", 42)]
1175 public class OptionalFooIsInt { }
1178 public class MyImporterWithExportStronglyTypedMetadata
1181 public Lazy
<IMyExporter
, IMetadataView
> ValueInfo { get; set; }
1185 public class MyImporterWithExportCollectionStronglyTypedMetadata
1188 public Collection
<Lazy
<IMyExporter
, IMetadataView
>> ValueInfoCol { get; set; }
1191 public class MyExporterWithFullMetadata
1193 [Export("MyStringContract")]
1194 public string String1 { get { return "String1"; }
}
1196 [Export("MyStringContract")]
1197 [ExportMetadata("Foo", "fooValue")]
1198 public string String2 { get { return "String2"; }
}
1200 [Export("MyStringContract")]
1201 [ExportMetadata("Bar", "barValue")]
1202 public string String3 { get { return "String3"; }
}
1204 [Export("MyStringContract")]
1205 [ExportMetadata("Foo", "fooValue")]
1206 [ExportMetadata("Bar", "barValue")]
1207 public string String4 { get { return "String4"; }
}
1211 [AttributeUsage(AttributeTargets
.All
, AllowMultiple
= true)]
1212 public class MyOption
: Attribute
1214 public MyOption(string name
, object value)
1217 OptionValues
= value;
1219 public string OptionNames { get; set; }
1220 public object OptionValues { get; set; }
1223 public interface IMyOptions
1225 IList
<string> OptionNames { get; }
1226 ICollection
<string> OptionValues { get; }
1229 public interface IMyOptionsAsIEnumerable
1231 IEnumerable
<string> OptionNames { get; }
1232 IEnumerable
<string> OptionValues { get; }
1235 public interface IMyOptionsAsArray
1237 string[] OptionNames { get; }
1238 string[] OptionValues { get; }
1242 [MyOption("name1", "value1")]
1243 [MyOption("name2", "value2")]
1244 [ExportMetadata("OptionNames", "name3", IsMultiple
= true)]
1245 [ExportMetadata("OptionValues", "value3", IsMultiple
= true)]
1246 public class ExportMultiple
1250 public interface IMyOption2
1252 string OptionNames { get; }
1253 string OptionValues { get; }