1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
6 using System.ComponentModel.Composition.Factories;
\r
7 using Microsoft.VisualStudio.TestTools.UnitTesting;
\r
8 using System.UnitTesting;
\r
9 using System.ComponentModel.Composition.Hosting;
\r
10 using System.ComponentModel.Composition.UnitTesting;
\r
12 namespace System.ComponentModel.Composition.AttributedModel
\r
15 public class AttributedModelCompositionTests
\r
18 public void PartContainingOnlyStaticExports_ShouldNotCauseInstanceToBeCreated()
\r
20 var container = ContainerFactory.CreateWithAttributedCatalog(typeof(HasOnlyStaticExports));
\r
22 Assert.AreEqual("Field", container.GetExportedValue<string>("Field"));
\r
23 Assert.AreEqual("Property", container.GetExportedValue<string>("Property"));
\r
24 Assert.IsNotNull("Method", container.GetExportedValue<Func<string>>("Method")());
\r
26 Assert.IsFalse(HasOnlyStaticExports.InstanceCreated);
\r
30 public void ExportOnAbstractBase_DoesNotReturnNull()
\r
31 { // 499393 - Classes inheriting from an exported
\r
32 // abstract class are exported as 'null'
\r
34 var container = ContainerFactory.Create();
\r
35 CompositionBatch batch = new CompositionBatch();
\r
37 var definition = PartDefinitionFactory.CreateAttributed(typeof(Derived));
\r
38 batch.AddPart(definition.CreatePart());
\r
39 container.Compose(batch);
\r
41 Assert.IsNotNull(container.GetExportedValueOrDefault<Base>());
\r
45 public void ReadOnlyFieldImport_ShouldThrowComposition()
\r
47 var importer = PartFactory.CreateAttributed(new ReadOnlyPropertyImport());
\r
48 var container = ContainerFactory.Create();
\r
49 CompositionBatch batch = new CompositionBatch();
\r
50 batch.AddPart(importer);
\r
51 batch.AddExportedValue("readonly", "new value");
\r
53 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotActivate,
\r
54 ErrorId.ReflectionModel_ImportNotWritable,
\r
55 RetryMode.DoNotRetry, () =>
\r
57 container.Compose(batch);
\r
62 public void ReadOnlyPropertyImport_ShouldThrowComposition()
\r
64 var importer = PartFactory.CreateAttributed(new ReadOnlyPropertyImport());
\r
65 var container = ContainerFactory.Create();
\r
66 CompositionBatch batch = new CompositionBatch();
\r
67 batch.AddPart(importer);
\r
68 batch.AddExportedValue("readonly", "new value");
\r
70 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotActivate,
\r
71 ErrorId.ReflectionModel_ImportNotWritable, RetryMode.DoNotRetry, () =>
\r
73 container.Compose(batch);
\r
78 public void WriteOnlyPropertyExport_ShouldThrowComposition()
\r
80 var importer = PartFactory.CreateAttributed(new WriteOnlyPropertyExport());
\r
81 var container = ContainerFactory.Create();
\r
82 CompositionBatch batch = new CompositionBatch();
\r
83 batch.AddPart(importer);
\r
84 container.Compose(batch);
\r
86 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotGetExportedValue, ErrorId.ReflectionModel_ExportNotReadable, () =>
\r
88 container.GetExportedValue<string>("writeonly");
\r
93 public void ImportValueMismatchFromInt32ToDateTime()
\r
95 var container = ContainerFactory.Create();
\r
96 CompositionBatch batch = new CompositionBatch();
\r
97 batch.AddPart(new ImportValueTypes());
\r
98 batch.AddExportedValue("DateTime", typeof(DateTime), 42);
\r
100 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
101 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
102 RetryMode.DoNotRetry, () =>
\r
104 container.Compose(batch);
\r
109 public void ImportValueMismatchFromInt16ToInt32()
\r
111 var container = ContainerFactory.Create();
\r
112 CompositionBatch batch = new CompositionBatch();
\r
114 batch.AddPart(new ImportValueTypes());
\r
115 batch.AddExportedValue("Int32", typeof(Int32), (short)10);
\r
117 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
118 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
119 RetryMode.DoNotRetry, () =>
\r
121 container.Compose(batch);
\r
127 public void ImportValueMismatchFromInt32ToInt16()
\r
129 var container = ContainerFactory.Create();
\r
130 CompositionBatch batch = new CompositionBatch();
\r
132 batch.AddPart(new ImportValueTypes());
\r
133 batch.AddExportedValue("Int16", typeof(Int16), (int)10);
\r
135 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
136 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
137 RetryMode.DoNotRetry, () =>
\r
139 container.Compose(batch);
\r
144 public void ImportValueMismatchFromInt32ToUInt32()
\r
146 var container = ContainerFactory.Create();
\r
147 CompositionBatch batch = new CompositionBatch();
\r
149 batch.AddPart(new ImportValueTypes());
\r
150 batch.AddExportedValue("UInt32", typeof(UInt32), (int)10);
\r
152 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
153 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
154 RetryMode.DoNotRetry, () =>
\r
156 container.Compose(batch);
\r
161 public void ImportValueMismatchFromUInt32ToInt32()
\r
163 var container = ContainerFactory.Create();
\r
164 CompositionBatch batch = new CompositionBatch();
\r
166 batch.AddPart(new ImportValueTypes());
\r
167 batch.AddExportedValue("Int32", typeof(Int32), (uint)10);
\r
169 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
170 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
171 RetryMode.DoNotRetry, () =>
\r
173 container.Compose(batch);
\r
178 public void ImportValueMismatchFromInt32ToInt64()
\r
180 var container = ContainerFactory.Create();
\r
181 CompositionBatch batch = new CompositionBatch();
\r
183 batch.AddPart(new ImportValueTypes());
\r
184 batch.AddExportedValue("Int64", typeof(Int64), (int)10);
\r
186 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
187 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
188 RetryMode.DoNotRetry, () =>
\r
190 container.Compose(batch);
\r
195 public void ImportValueMismatchFromSingleToDouble()
\r
197 var container = ContainerFactory.Create();
\r
198 CompositionBatch batch = new CompositionBatch();
\r
200 batch.AddPart(new ImportValueTypes());
\r
201 batch.AddExportedValue("Double", typeof(Double), (float)10);
\r
203 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
204 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
205 RetryMode.DoNotRetry, () =>
\r
207 container.Compose(batch);
\r
212 public void ImportValueMismatchFromDoubleToSingle()
\r
214 var container = ContainerFactory.Create();
\r
215 CompositionBatch batch = new CompositionBatch();
\r
217 batch.AddPart(new ImportValueTypes());
\r
218 batch.AddExportedValue("Single", typeof(Single), (double)10);
\r
220 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
221 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
222 RetryMode.DoNotRetry, () =>
\r
224 container.Compose(batch);
\r
229 public void ImportValueMismatchFromSingleToInt32()
\r
231 var container = ContainerFactory.Create();
\r
232 CompositionBatch batch = new CompositionBatch();
\r
234 batch.AddPart(new ImportValueTypes());
\r
235 batch.AddExportedValue("Int32", typeof(Int32), (float)10);
\r
237 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
238 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
239 RetryMode.DoNotRetry, () =>
\r
241 container.Compose(batch);
\r
246 public void ImportValueMismatchFromInt32ToSingle()
\r
248 var container = ContainerFactory.Create();
\r
249 CompositionBatch batch = new CompositionBatch();
\r
251 batch.AddPart(new ImportValueTypes());
\r
252 batch.AddExportedValue("Single", typeof(Single), (int)10);
\r
254 CompositionAssert.ThrowsError(ErrorId.ImportEngine_PartCannotSetImport,
\r
255 ErrorId.ReflectionModel_ImportNotAssignableFromExport,
\r
256 RetryMode.DoNotRetry, () =>
\r
258 container.Compose(batch);
\r
263 public void MemberExports()
\r
265 var exporter = PartFactory.CreateAttributed(new ObjectWithMemberExports());
\r
266 var container = ContainerFactory.Create();
\r
267 CompositionBatch batch = new CompositionBatch();
\r
268 batch.AddPart(exporter);
\r
269 container.Compose(batch);
\r
271 var filedExports = container.GetExports<int>("field");
\r
272 ExportsAssert.AreEqual(filedExports, 1, 5);
\r
274 var readonlyExports = container.GetExports<int>("readonly");
\r
275 ExportsAssert.AreEqual(readonlyExports, 2, 6);
\r
277 var propertyExports = container.GetExports<int>("property");
\r
278 ExportsAssert.AreEqual(propertyExports, 3, 7);
\r
280 var methodExports = container.GetExportedValues<Func<int, int>>("func").Select(f => f(0));
\r
281 EnumerableAssert.AreEqual(methodExports, 4, 8);
\r
285 public void TestExportedValueCachesValue()
\r
287 var container = ContainerFactory.Create();
\r
288 var exporter = new ExportsMutableProperty();
\r
289 exporter.Property = "Value1";
\r
291 container.ComposeParts(exporter);
\r
293 Assert.AreEqual("Value1", container.GetExportedValue<string>("Property"));
\r
295 exporter.Property = "Value2";
\r
297 // Exported value should have been cached and so it shouldn't change
\r
298 Assert.AreEqual("Value1", container.GetExportedValue<string>("Property"));
\r
304 public void TestExportedValueCachesNullValue()
\r
306 var container = ContainerFactory.Create();
\r
307 var exporter = new ExportsMutableProperty();
\r
308 exporter.Property = null;
\r
310 container.ComposeParts(exporter);
\r
312 Assert.IsNull(container.GetExportedValue<string>("Property"));
\r
314 exporter.Property = "Value1";
\r
316 // Exported value should have been cached and so it shouldn't change
\r
317 Assert.IsNull(container.GetExportedValue<string>("Property"));
\r
320 public class ExportsMutableProperty
\r
322 [Export("Property")]
\r
323 public string Property { get; set; }
\r
326 public class ReadOnlyFieldImport
\r
328 [Import("readonly")]
\r
329 public readonly string Value = "Value";
\r
332 public class ReadOnlyPropertyImport
\r
334 [Import("readonly")]
\r
335 public string Value
\r
337 get { return "Value"; }
\r
341 public class WriteOnlyPropertyExport
\r
343 [Export("writeonly")]
\r
344 public string Value
\r
350 public class ObjectWithMemberExports
\r
353 public static int staticField = 1;
\r
355 [Export("readonly")]
\r
356 public static readonly int staticReadonly = 2;
\r
358 [Export("property")]
\r
359 public static int StaticProperty { get { return 3; } }
\r
362 public static int StaticMethod(int arg1) { return 4; }
\r
365 public int instanceField = 5;
\r
367 [Export("readonly")]
\r
368 public readonly int instanceReadonly = 6;
\r
370 [Export("property")]
\r
371 public int InstanceProperty { get { return 7; } }
\r
374 public int InstanceMethod(int arg1) { return 8; }
\r
377 public class HasOnlyStaticExports
\r
379 public static bool InstanceCreated;
\r
381 public HasOnlyStaticExports()
\r
383 InstanceCreated = true;
\r
387 public static string Field = "Field";
\r
389 [Export("Property")]
\r
390 public static string Property
\r
392 get { return "Property"; }
\r
396 public static string Method()
\r
402 [InheritedExport(typeof(Base))]
\r
403 public abstract class Base
\r
407 [Export(typeof(Derived))]
\r
408 public class Derived : Base
\r
412 public class ImportValueTypes
\r
414 [Import("Int16", AllowDefault = true)]
\r
421 [Import("Int32", AllowDefault = true)]
\r
428 [Import("UInt32", AllowDefault = true)]
\r
429 [CLSCompliant(false)]
\r
436 [Import("Int64", AllowDefault = true)]
\r
443 [Import("Single", AllowDefault = true)]
\r
444 public float Single
\r
450 [Import("Double", AllowDefault = true)]
\r
451 public double Double
\r
457 [Import("DateTime", AllowDefault = true)]
\r
458 public DateTime DateTime
\r