1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.Collections.Generic;
\r
6 using System.ComponentModel.Composition;
\r
7 using System.ComponentModel.Composition.Factories;
\r
8 using System.ComponentModel.Composition.Hosting;
\r
10 using System.UnitTesting;
\r
11 using Microsoft.VisualStudio.TestTools.UnitTesting;
\r
12 using System.Reflection;
\r
13 using System.ComponentModel.Composition.Primitives;
\r
15 namespace System.ComponentModel.Composition
\r
18 public class MetadataAttributeTests
\r
21 [TestProperty("Type", "Integration")]
\r
22 public void UntypedStructureTest()
\r
24 var container = ContainerFactory.Create();
\r
25 CompositionBatch batch = new CompositionBatch();
\r
26 batch.AddPart(AttributedModelServices.CreatePart(new BasicTestComponent()));
\r
27 container.Compose(batch);
\r
28 var export = container.GetExport<BasicTestComponent, IDictionary<string, object>>();
\r
31 Assert.IsNotNull(export.Metadata, "It should have metadata");
\r
32 Assert.AreEqual("One", export.Metadata["String1"], "Property attribute should copy straight across");
\r
33 Assert.AreEqual("Two", export.Metadata["String2"], "Property attribute should copy straight across");
\r
34 var e = export.Metadata["Numbers"] as IList<int>;
\r
35 Assert.IsNotNull(e, "Should get a collection of numbers");
\r
36 Assert.IsTrue(e.Contains(1), "Should have 1 in the list");
\r
37 Assert.IsTrue(e.Contains(2), "Should have 2 in the list");
\r
38 Assert.IsTrue(e.Contains(3), "Should have 3 in the list");
\r
39 Assert.AreEqual(3, e.Count, "Should be three numbers total");
\r
43 // Silverlight doesn't support strongly typed metadata
\r
45 [TestProperty("Type", "Integration")]
\r
46 public void StronglyTypedStructureTest()
\r
48 var container = ContainerFactory.Create();
\r
49 CompositionBatch batch = new CompositionBatch();
\r
50 batch.AddPart(AttributedModelServices.CreatePart(new BasicTestComponent()));
\r
51 container.Compose(batch);
\r
53 var export = container.GetExport<BasicTestComponent, IStronglyTypedStructure>();
\r
55 Assert.IsNotNull(export.Metadata, "It should have metadata");
\r
56 Assert.AreEqual("One", export.Metadata.String1, "Property should copy straight across");
\r
57 Assert.AreEqual("Two", export.Metadata.String2, "Property should copy straight across");
\r
58 Assert.IsTrue(export.Metadata.Numbers.Contains(1), "Should have 1 in the list");
\r
59 Assert.IsTrue(export.Metadata.Numbers.Contains(2), "Should have 2 in the list");
\r
60 Assert.IsTrue(export.Metadata.Numbers.Contains(3), "Should have 3 in the list");
\r
61 Assert.AreEqual(3, export.Metadata.Numbers.Length, "Should be three numbers total");
\r
63 #endif //!SILVERLIGHT
\r
66 // Should cause a conflict with the multiple nature of Name.Bar because
\r
67 // it isn't marked with IsMultiple=true
\r
68 [ExportMetadata("Bar", "Blah")]
\r
71 [PartNotDiscoverable]
\r
72 public class BasicTestComponentWithInvalidMetadata
\r
77 [TestProperty("Type", "Integration")]
\r
78 public void InvalidMetadataAttributeTest()
\r
80 ComposablePart part = AttributedModelServices.CreatePart(new BasicTestComponentWithInvalidMetadata());
\r
81 ExportDefinition export = part.ExportDefinitions.First();
\r
83 var ex = ExceptionAssert.Throws<InvalidOperationException>(RetryMode.DoNotRetry, () =>
\r
85 var metadata = export.Metadata;
\r
88 Assert.IsTrue(ex.Message.Contains("Bar"));
\r
91 [AttributeUsage(AttributeTargets.All)]
\r
93 public class MetadataWithInvalidCustomAttributeType : Attribute
\r
95 public PersonClass Person { get { return new PersonClass(); } }
\r
97 public class PersonClass
\r
99 public string First { get { return "George"; } }
\r
100 public string Last { get { return "Washington"; } }
\r
105 [MetadataWithInvalidCustomAttributeType]
\r
106 [PartNotDiscoverable]
\r
107 public class ClassWithInvalidCustomAttributeType
\r
113 public void InvalidAttributType_CustomType_ShouldThrow()
\r
115 ComposablePart part = AttributedModelServices.CreatePart(new ClassWithInvalidCustomAttributeType());
\r
116 ExportDefinition export = part.ExportDefinitions.First();
\r
118 // Should throw InvalidOperationException during discovery because
\r
119 // the person class is an invalid metadata type
\r
120 ExceptionAssert.Throws<InvalidOperationException>(RetryMode.DoNotRetry, () =>
\r
122 var metadata = export.Metadata;
\r
126 [AttributeUsage(AttributeTargets.All)]
\r
127 [MetadataAttribute]
\r
128 public class MetadataWithInvalidVersionPropertyAttributeType : Attribute
\r
130 public MetadataWithInvalidVersionPropertyAttributeType()
\r
132 this.Version = new Version(1, 1);
\r
134 public Version Version { get; set; }
\r
138 [MetadataWithInvalidVersionPropertyAttributeType]
\r
139 [PartNotDiscoverable]
\r
140 public class ClassWithInvalidVersionPropertyAttributeType
\r
146 public void InvalidAttributType_VersionPropertyType_ShouldThrow()
\r
148 ComposablePart part = AttributedModelServices.CreatePart(new ClassWithInvalidVersionPropertyAttributeType());
\r
149 ExportDefinition export = part.ExportDefinitions.First();
\r
151 // Should throw InvalidOperationException during discovery because
\r
152 // the person class is an invalid metadata type
\r
153 ExceptionAssert.Throws<InvalidOperationException>(RetryMode.DoNotRetry, () =>
\r
155 var metadata = export.Metadata;
\r
159 [MetadataAttribute]
\r
160 public class BaseMetadataAttribute : Attribute
\r
162 public string BaseKey { get { return "BaseValue"; } }
\r
165 public class DerivedMetadataAttribute : BaseMetadataAttribute
\r
167 public string DerivedKey { get { return "DerivedValue"; } }
\r
172 public class ExportWithDerivedMetadataAttribute { }
\r
175 public void DerivedMetadataAttributeAttribute_ShouldSupplyMetadata()
\r
177 ComposablePart part = AttributedModelServices.CreatePart(new ExportWithDerivedMetadataAttribute());
\r
178 ExportDefinition export = part.ExportDefinitions.Single();
\r
180 Assert.AreEqual("BaseValue", export.Metadata["BaseKey"]);
\r
181 Assert.AreEqual("DerivedValue", export.Metadata["DerivedKey"]);
\r
185 [AttributeUsage(AttributeTargets.All)]
\r
186 [MetadataAttribute]
\r
187 public class BasicMetadataAttribute : Attribute
\r
189 public string String1 { get { return "One"; } }
\r
191 public string String2 { get { return "Two"; } }
\r
193 public int[] Numbers { get { return new int[] { 1, 2, 3 }; } }
\r
195 public CreationPolicy Policy { get { return CreationPolicy.NonShared; } }
\r
197 public Type Type { get { return typeof(BasicMetadataAttribute); } }
\r
200 public interface IStronglyTypedStructure
\r
202 string String1 { get; }
\r
203 string String2 { get; }
\r
204 int[] Numbers { get; }
\r
205 CreationPolicy Policy { get; }
\r
209 [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
\r
210 [MetadataAttribute]
\r
211 public class Name : Attribute
\r
213 public Name(string name) { Bar = name; }
\r
215 public string Bar { set; get; }
\r
218 [PartNotDiscoverable]
\r
221 public class BasicTestComponent
\r