update MEF to preview 9
[mcs.git] / class / System.ComponentModel.Composition / Tests / ComponentModelUnitTest / System / ComponentModel / Composition / MetadataTests.cs
blob73d8c873c5d5b134074f505be0cb2204c309d584
1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
4 using System;
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;
11 using System.Linq;
12 using Microsoft.VisualStudio.TestTools.UnitTesting;
13 using System.UnitTesting;
14 using System.Reflection;
15 using System.Collections.ObjectModel;
17 namespace System.ComponentModel.Composition
19 [TestClass]
20 public class MetadataTests
22 #region Tests for metadata on exports
24 public enum SimpleEnum
26 First
29 [PartNotDiscoverable]
30 [Export]
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
41 [PartNotDiscoverable]
42 [Export]
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
53 [PartNotDiscoverable]
54 [Export]
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
65 [PartNotDiscoverable]
66 [Export]
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; }
80 int Int { get; }
81 float Float { get; }
82 SimpleEnum Enum { get; }
83 Type Type { get; }
84 object Object { get; }
87 [TestMethod]
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);
103 [TestMethod]
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);
119 [TestMethod]
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());
129 [TestMethod]
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());
139 [TestMethod]
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");
175 [TestMethod]
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)]
214 [MetadataAttribute]
215 public class BadStrongMetadata : Attribute
217 public string SelfConflicted { get { return "SelfConflictedValue"; } }
220 [Export]
221 [BadStrongMetadata]
222 [ExportMetadata("InvalidCollection", "InvalidCollectionValue1")]
223 [ExportMetadata("InvalidCollection", "InvalidCollectionValue2", IsMultiple = true)]
224 [BadStrongMetadata]
225 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue1")]
226 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue2")]
227 [ExportMetadata("GoodOne1", "GoodOneValue1")]
228 [ExportMetadata("ConflictedOne1", "ConfilictedOneValue1")]
229 [GoodStrongMetadata]
230 [ExportMetadata("ConflictedOne2", "ConflictedOne2Value2")]
231 [PartNotDiscoverable]
232 public class MyExporterWithInvalidMetadata
234 [Export("ContractForInvalidMetadata")]
235 [ExportMetadata("ConflictedOne1", "ConfilictedOneValue1")]
236 [GoodStrongMetadata]
237 [ExportMetadata("ConflictedOne2", "ConflictedOne2Value2")]
238 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue1")]
239 [ExportMetadata("RepeatedMetadata", "RepeatedMetadataValue2")]
240 [BadStrongMetadata]
241 [ExportMetadata("InvalidCollection", "InvalidCollectionValue1")]
242 [ExportMetadata("InvalidCollection", "InvalidCollectionValue2", IsMultiple = true)]
243 [BadStrongMetadata]
244 [ExportMetadata("GoodOne1", "GoodOneValue1")]
245 public double DoSomething() { return 0.618; }
248 [Export]
249 [ExportMetadata("DuplicateMetadataName", "My Name")]
250 [ExportMetadata("DuplicateMetadataName", "Your Name")]
251 [PartNotDiscoverable]
252 public class ClassWithInvalidDuplicateMetadataOnType
257 [TestMethod]
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
273 [Export]
274 [ExportMetadata("DuplicateMetadataName", "My Name")]
275 [ExportMetadata("DuplicateMetadataName", "Your Name")]
276 public ClassWithDuplicateMetadataOnMember Member { get; set; }
279 [TestMethod]
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"));
293 [Export]
294 [ExportMetadata("DuplicateMetadataName", "My Name", IsMultiple=true)]
295 [ExportMetadata("DuplicateMetadataName", "Your Name", IsMultiple=true)]
296 public class ClassWithValidDuplicateMetadataOnType
301 [TestMethod]
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
319 [Export]
320 [ExportMetadata("DuplicateMetadataName", "My Name", IsMultiple=true)]
321 [ExportMetadata("DuplicateMetadataName", "Your Name", IsMultiple=true)]
322 public ClassWithDuplicateMetadataOnMember Member { get; set; }
325 [TestMethod]
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);
341 [Export]
342 [ExportMetadata(CompositionConstants.PartCreationPolicyMetadataName, "My Policy")]
343 [PartNotDiscoverable]
344 public class ClassWithReservedMetadataValue
349 [TestMethod]
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));
363 #endregion
365 #region Tests for weakly supported metadata as part of contract
367 [TestMethod]
368 [WorkItem(468388)]
369 [Ignore]
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());
379 Assert.Fail();
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'");
388 [TestMethod]
389 [WorkItem(472538)]
390 [Ignore]
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);
411 [TestMethod]
412 [WorkItem(468388)]
413 [Ignore]
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());
424 Assert.Fail();
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");
433 [TestMethod]
434 [WorkItem(468388)]
435 [Ignore]
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());
446 Assert.Fail();
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");
458 [TestMethod]
459 [WorkItem(472538)]
460 [Ignore]
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);
478 [TestMethod]
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());
496 [TestMethod]
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());
513 [TestMethod]
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);
537 #endregion
539 #region Tests for strongly typed metadata as part of contract
541 [TestMethod]
542 [WorkItem(468388)]
543 [Ignore]
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());
554 Assert.Fail();
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'");
564 [TestMethod]
565 [WorkItem(468388)]
566 [Ignore]
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());
578 Assert.Fail();
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'");
588 [TestMethod]
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>();
602 [TestMethod]
603 [WorkItem(468388)]
604 [Ignore]
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'");
626 [TestMethod]
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");
636 [TestMethod]
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");
646 [TestMethod]
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");
656 [TestMethod]
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());
666 [TestMethod]
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);
676 #endregion
679 [ExportMetadata("Name", "FromBaseType")]
680 public abstract class BaseClassWithMetadataButNoExport
684 [Export(typeof(BaseClassWithMetadataButNoExport))]
685 public class DerivedClassWithExportButNoMetadata : BaseClassWithMetadataButNoExport
689 [TestMethod]
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
712 [TestMethod]
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
736 [TestMethod]
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"]);
751 [Export]
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
769 [TestMethod]
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);
781 [Export]
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
790 [TestMethod]
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)]
805 [MetadataAttribute]
806 public class DataAttribute : Attribute
808 public object Object { get; set; }
811 [Export]
812 [Data(Object="42")]
813 [Data(Object = "10")]
814 public class ExportWithMultipleMetadata_ExportStringsAsObjects
818 [Export]
819 [Data(Object = "42")]
820 [Data(Object = "10")]
821 [Data(Object = null)]
822 public class ExportWithMultipleMetadata_ExportStringsAsObjects_WithNull
826 [Export]
827 [Data(Object = 42)]
828 [Data(Object = 10)]
829 public class ExportWithMultipleMetadata_ExportIntsAsObjects
833 [Export]
834 [Data(Object = null)]
835 [Data(Object = 42)]
836 [Data(Object = 10)]
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; }
857 [TestMethod]
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);
871 [TestMethod]
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);
885 [TestMethod]
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);
899 [TestMethod]
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);
915 [MetadataAttribute]
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; }
929 [Export]
930 [Order(Before = "Step3")]
931 [Order(Before = "Step2")]
932 public class OrderedItemBeforesOnly
936 [TestMethod]
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]);
960 [MetadataAttribute]
961 [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
962 public class DataTypeAttribute : Attribute
964 public Type Type { get; set; }
967 public interface ITypesMetadataView
969 Type[] Type { get; }
972 [Export]
973 [DataType(Type = typeof(int))]
974 [DataType(Type = typeof(string))]
975 public class ItemWithTypeExports
979 [Export]
980 [DataType(Type = typeof(int))]
981 [DataType(Type = typeof(string))]
982 [DataType(Type = null)]
983 public class ItemWithTypeExports_WithNulls
987 [Export]
988 [DataType(Type = null)]
989 [DataType(Type = null)]
990 [DataType(Type = null)]
991 public class ItemWithTypeExports_WithAllNulls
995 [TestMethod]
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);
1008 [TestMethod]
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);
1021 [TestMethod]
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]);
1037 [Export]
1038 [ExportMetadata(null, "ValueOfNullKey")]
1039 public class ClassWithNullMetadataKey
1043 [TestMethod]
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
1061 [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)]
1081 [MetadataAttribute]
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 { }
1093 [Export]
1094 [Export(typeof(IMyExporter))]
1095 public class MyExporterWithNoMetadata : IMyExporter
1099 [Export]
1100 [Export(typeof(IMyExporter))]
1101 [ExportMetadata("Foo", "Bar")]
1102 public class MyExporterWithMetadata : IMyExporter
1107 public interface IMetadataFoo
1109 string Foo { get; }
1112 public interface IMetadataBar
1114 string Bar { get; }
1117 [Export]
1118 public class MyImporterWithExport
1120 [Import(typeof(MyExporterWithNoMetadata))]
1121 public Lazy<MyExporterWithNoMetadata, IMetadataFoo> ValueInfo { get; set; }
1124 [Export]
1125 public class SingleImportWithAllowDefault
1127 [Import("Import", AllowDefault = true)]
1128 public Lazy<object> Import { get; set; }
1131 [Export]
1132 public class SingleImport
1134 [Import("Import")]
1135 public Lazy<object> Import { get; set; }
1138 public interface IFooMetadataView
1140 string Foo { get; }
1143 [Export]
1144 public class MyImporterWithExportCollection
1146 [ImportMany(typeof(MyExporterWithNoMetadata))]
1147 public IEnumerable<Lazy<MyExporterWithNoMetadata, IFooMetadataView>> ValueInfoCol { get; set; }
1150 [Export]
1151 public class MyImporterWithExportForSelectiveImport
1153 [Import]
1154 public Lazy<IMyExporter, IFooMetadataView> ValueInfo { get; set; }
1157 [Export]
1158 public class MyImporterWithExportCollectionForSelectiveImport
1160 [ImportMany]
1161 public Collection<Lazy<IMyExporter, IFooMetadataView>> ValueInfoCol { get; set; }
1164 public interface IMetadataView
1166 string Foo { get; }
1168 [System.ComponentModel.DefaultValue(null)]
1169 string OptionalFoo { get; }
1172 [Export]
1173 [ExportMetadata("Foo", "fooValue3")]
1174 [ExportMetadata("OptionalFoo", 42)]
1175 public class OptionalFooIsInt { }
1177 [Export]
1178 public class MyImporterWithExportStronglyTypedMetadata
1180 [Import]
1181 public Lazy<IMyExporter, IMetadataView> ValueInfo { get; set; }
1184 [Export]
1185 public class MyImporterWithExportCollectionStronglyTypedMetadata
1187 [ImportMany]
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"; } }
1210 [MetadataAttribute]
1211 [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
1212 public class MyOption : Attribute
1214 public MyOption(string name, object value)
1216 OptionNames = name;
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; }
1241 [Export]
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; }