1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections;
6 using System.Collections.Generic;
7 using System.ComponentModel.DataAnnotations;
8 using System.Composition.Convention;
9 using System.Composition.Hosting.Core;
10 using System.Diagnostics;
11 using System.Reflection;
12 using Xunit;
13 
14 namespace System.Composition.Hosting.Tests
15 {
16     public class ContainerConfigurationTests
17     {
18         [Fact]
19         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithProvider_ValidProvider_RegistersProvider()20         public void WithProvider_ValidProvider_RegistersProvider()
21         {
22             var configuration = new ContainerConfiguration();
23 
24             var provider = new ExportProvider { Result = 10 };
25             Assert.Same(configuration, configuration.WithProvider(provider));
26 
27             CompositionHost container = configuration.CreateContainer();
28             Assert.Equal(0, provider.CalledGetExportDescriptors);
29             Assert.Equal(0, provider.CalledGetExportDescriptors);
30 
31             Assert.Equal(10, container.GetExport<int>());
32             Assert.Equal(1, provider.CalledGetExportDescriptors);
33             Assert.Equal(1, provider.CalledGetExportDescriptors);
34         }
35 
36         public class ExportProvider : ExportDescriptorProvider
37         {
38             public object Result { get; set; }
39             public int CalledGetExportDescriptors { get; set; }
40             public int CalledCompositeActivator { get; set; }
41 
GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)42             public override IEnumerable<ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor descriptorAccessor)
43             {
44                 CalledGetExportDescriptors++;
45                 return new[]
46                 {
47                     new ExportDescriptorPromise(contract, "origin", false, () => new CompositionDependency[0], dependencies => ExportDescriptor.Create(CompositeActivator, new Dictionary<string, object>()))
48                 };
49             }
50 
CompositeActivator(LifetimeContext context, CompositionOperation operation)51             public object CompositeActivator(LifetimeContext context, CompositionOperation operation)
52             {
53                 CalledCompositeActivator++;
54                 return Result;
55             }
56         }
57 
58         [Fact]
WithProvider_NullProvider_ThrowsArgumentNullException()59         public void WithProvider_NullProvider_ThrowsArgumentNullException()
60         {
61             var configuration = new ContainerConfiguration();
62             AssertExtensions.Throws<ArgumentNullException>("exportDescriptorProvider", () => configuration.WithProvider(null));
63         }
64 
65         [Fact]
66         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithDefaultConventions_PartWithNoMatchingConvention_Success()67         public void WithDefaultConventions_PartWithNoMatchingConvention_Success()
68         {
69             var conventions = new ConventionBuilder();
70             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
71 
72             var configuration = new ContainerConfiguration();
73             configuration.WithPart(typeof(ExportedProperty));
74             Assert.Same(configuration, configuration.WithDefaultConventions(conventions));
75 
76             CompositionHost container = configuration.CreateContainer();
77             Assert.Equal("A", container.GetExport<string>());
78         }
79 
80         [Fact]
81         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithDefaultConventions_IEnumerablePartsWithNoMatchingConvention_Success()82         public void WithDefaultConventions_IEnumerablePartsWithNoMatchingConvention_Success()
83         {
84             var conventions = new ConventionBuilder();
85             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
86 
87             var configuration = new ContainerConfiguration();
88             configuration.WithParts((IEnumerable<Type>)new Type[] { typeof(ExportedProperty) });
89             Assert.Same(configuration, configuration.WithDefaultConventions(conventions));
90 
91             CompositionHost container = configuration.CreateContainer();
92             Assert.Equal("A", container.GetExport<string>());
93         }
94 
95         [Fact]
96         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithDefaultConventions_PartsArrayWithNoMatchingConvention_Success()97         public void WithDefaultConventions_PartsArrayWithNoMatchingConvention_Success()
98         {
99             var conventions = new ConventionBuilder();
100             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
101 
102             var configuration = new ContainerConfiguration();
103             configuration.WithParts(new Type[] { typeof(ExportedProperty) });
104             Assert.Same(configuration, configuration.WithDefaultConventions(conventions));
105 
106             CompositionHost container = configuration.CreateContainer();
107             Assert.Equal("A", container.GetExport<string>());
108         }
109 
110         [Fact]
111         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithDefaultConventions_PartTNoMatchingConvention_Success()112         public void WithDefaultConventions_PartTNoMatchingConvention_Success()
113         {
114             var conventions = new ConventionBuilder();
115             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
116 
117             var configuration = new ContainerConfiguration();
118             configuration.WithPart<ExportedProperty>();
119             Assert.Same(configuration, configuration.WithDefaultConventions(conventions));
120 
121             CompositionHost container = configuration.CreateContainer();
122             Assert.Equal("A", container.GetExport<string>());
123         }
124 
125         public class ExportedProperty
126         {
127             [Export]
128             public string Property => "A";
129         }
130 
131         [Fact]
WithDefaultConventions_NullConventions_ThrowsArgumentNullException()132         public void WithDefaultConventions_NullConventions_ThrowsArgumentNullException()
133         {
134             var configuration = new ContainerConfiguration();
135             AssertExtensions.Throws<ArgumentNullException>("conventions", () => configuration.WithDefaultConventions(null));
136         }
137 
138         [Fact]
WithDefaultConventions_AlreadyHasDefaultConventions_ThrowsInvalidOperationException()139         public void WithDefaultConventions_AlreadyHasDefaultConventions_ThrowsInvalidOperationException()
140         {
141             var configuration = new ContainerConfiguration();
142             configuration.WithDefaultConventions(new ConventionBuilder());
143             Assert.Throws<InvalidOperationException>(() => configuration.WithDefaultConventions(new ConventionBuilder()));
144         }
145 
146         [Fact]
147         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithPartT_Convention_Success()148         public void WithPartT_Convention_Success()
149         {
150             var conventions = new ConventionBuilder();
151             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
152 
153             var configuration = new ContainerConfiguration();
154             Assert.Same(configuration, configuration.WithPart<ExportedProperty>(conventions));
155 
156             CompositionHost container = configuration.CreateContainer();
157             Assert.Equal("A", container.GetExport<string>());
158         }
159 
160         [Fact]
161         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithPart_Convention_Success()162         public void WithPart_Convention_Success()
163         {
164             var conventions = new ConventionBuilder();
165             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
166 
167             var configuration = new ContainerConfiguration();
168             Assert.Same(configuration, configuration.WithPart(typeof(ExportedProperty), conventions));
169 
170             CompositionHost container = configuration.CreateContainer();
171             Assert.Equal("A", container.GetExport<string>());
172         }
173 
174         [Fact]
WithPart_NullPartType_ThrowsArgumentNullException()175         public void WithPart_NullPartType_ThrowsArgumentNullException()
176         {
177             var configuration = new ContainerConfiguration();
178             AssertExtensions.Throws<ArgumentNullException>("partType", () => configuration.WithPart(null));
179             AssertExtensions.Throws<ArgumentNullException>("partType", () => configuration.WithPart(null, new ConventionBuilder()));
180         }
181 
182         [Fact]
183         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
WithParts_Convention_Success()184         public void WithParts_Convention_Success()
185         {
186             var conventions = new ConventionBuilder();
187             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
188 
189             var configuration = new ContainerConfiguration();
190             Assert.Same(configuration, configuration.WithParts(new Type[] { typeof(ExportedProperty) }, conventions));
191 
192             CompositionHost container = configuration.CreateContainer();
193             Assert.Equal("A", container.GetExport<string>());
194         }
195 
196         [Fact]
WithParts_NullPartTypes_ThrowsArgumentNullException()197         public void WithParts_NullPartTypes_ThrowsArgumentNullException()
198         {
199             var configuration = new ContainerConfiguration();
200             AssertExtensions.Throws<ArgumentNullException>("partTypes", () => configuration.WithParts(null));
201             AssertExtensions.Throws<ArgumentNullException>("partTypes", () => configuration.WithParts((IEnumerable<Type>)null));
202             AssertExtensions.Throws<ArgumentNullException>("partTypes", () => configuration.WithParts(null, new ConventionBuilder()));
203         }
204 
205         [Fact]
WithParts_NullItemInPartTypes_ThrowsArgumentNullExceptionOnCreation()206         public void WithParts_NullItemInPartTypes_ThrowsArgumentNullExceptionOnCreation()
207         {
208             ContainerConfiguration configuration = new ContainerConfiguration().WithParts(new Type[] { null });
209             AssertExtensions.Throws<ArgumentNullException>("type", () => configuration.CreateContainer());
210         }
211 
212         [Fact]
WithAssembly_Assembly_ThrowsCompositionFailedExceptionOnCreation()213         public void WithAssembly_Assembly_ThrowsCompositionFailedExceptionOnCreation()
214         {
215             var configuration = new ContainerConfiguration();
216             Assert.Same(configuration, configuration.WithAssembly(typeof(ExportedProperty).Assembly));
217             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
218         }
219 
220         [Fact]
WithAssembly_AssemblyConventions_ThrowsCompositionFailedExceptionOnCreation()221         public void WithAssembly_AssemblyConventions_ThrowsCompositionFailedExceptionOnCreation()
222         {
223             var conventions = new ConventionBuilder();
224             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
225 
226             var configuration = new ContainerConfiguration();
227             Assert.Same(configuration, configuration.WithAssembly(typeof(ExportedProperty).Assembly, conventions));
228             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
229         }
230 
231         [Fact]
WithAssemblies_Assemblies_ThrowsCompositionFailedExceptionOnCreation()232         public void WithAssemblies_Assemblies_ThrowsCompositionFailedExceptionOnCreation()
233         {
234             var configuration = new ContainerConfiguration();
235             Assert.Same(configuration, configuration.WithAssemblies(new Assembly[] { typeof(ExportedProperty).Assembly }));
236             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
237         }
238 
239         [Fact]
WithAssemblies_AssembliesAndConvention_ThrowsCompositionFailedExceptionOnCreation()240         public void WithAssemblies_AssembliesAndConvention_ThrowsCompositionFailedExceptionOnCreation()
241         {
242             var conventions = new ConventionBuilder();
243             conventions.ForType<ExportedProperty>().ExportProperty(b => b.Property);
244 
245             var configuration = new ContainerConfiguration();
246             Assert.Same(configuration, configuration.WithAssemblies(new Assembly[] { typeof(ExportedProperty).Assembly }, conventions));
247             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
248         }
249 
250         [Fact]
WithAssemblies_NullAssemblies_ThrowsArgumentNullException()251         public void WithAssemblies_NullAssemblies_ThrowsArgumentNullException()
252         {
253             var configuration = new ContainerConfiguration();
254             AssertExtensions.Throws<ArgumentNullException>("assemblies", () => configuration.WithAssemblies(null));
255             AssertExtensions.Throws<ArgumentNullException>("assemblies", () => configuration.WithAssemblies(null, new ConventionBuilder()));
256         }
257 
258         [Fact]
WithAssemby_Null_ThrowsNullReferenceExceptionOnCreation()259         public void WithAssemby_Null_ThrowsNullReferenceExceptionOnCreation()
260         {
261             ContainerConfiguration configuration = new ContainerConfiguration().WithAssembly(null);
262             Assert.Throws<NullReferenceException>(() => configuration.CreateContainer());
263         }
264 
265         [Fact]
266         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_ExportedSubClass_Success()267         public void CreateContainer_ExportedSubClass_Success()
268         {
269             CompositionHost container = new ContainerConfiguration()
270                 .WithPart(typeof(Derived))
271                 .CreateContainer();
272             Assert.Equal("Derived", container.GetExport<Derived>().Prop);
273         }
274 
275         [Export]
276         public class Derived : Base
277         {
278             new public string Prop { get; set; } = "Derived";
279         }
280 
281         public class Base
282         {
283             public object Prop { get; set; } = "Derived";
284         }
285 
286         [Fact]
287         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_OpenGenericTypes_Success()288         public void CreateContainer_OpenGenericTypes_Success()
289         {
290             var conventions = new ConventionBuilder();
291             conventions.ForTypesDerivedFrom<IContainer>()
292                 .Export<IContainer>();
293             conventions.ForTypesDerivedFrom(typeof(IRepository<>))
294                 .Export(t => t.AsContractType(typeof(IRepository<>)));
295 
296             CompositionHost container = new ContainerConfiguration()
297                 .WithParts(new Type[] { typeof(EFRepository<>), typeof(Container) }, conventions)
298                 .CreateContainer();
299             Assert.Equal(0, container.GetExport<IRepository<int>>().Fetch());
300         }
301 
302         public interface IContainer { }
303         public class Container : IContainer { }
304 
305         public interface IRepository<T>
306         {
Fetch()307             T Fetch();
308         }
309 
310         public class EFRepository<T> : IRepository<T>
311         {
EFRepository(IContainer test)312             public EFRepository(IContainer test) { }
Fetch()313             public T Fetch() => default(T);
314         }
315 
316         [Fact]
317         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_ImportConventionsWithInheritedProperties_Success()318         public void CreateContainer_ImportConventionsWithInheritedProperties_Success()
319         {
320             var conventions = new ConventionBuilder();
321             conventions.ForType<Imported>().Export();
322             conventions.ForType<DerivedFromBaseWithImport>()
323                 .ImportProperty(b => b.Imported)
324                 .Export();
325 
326             CompositionHost container = new ContainerConfiguration()
327                 .WithDefaultConventions(conventions)
328                 .WithParts(typeof(Imported), typeof(DerivedFromBaseWithImport))
329                 .CreateContainer();
330 
331             DerivedFromBaseWithImport export = container.GetExport<DerivedFromBaseWithImport>();
332             Assert.IsAssignableFrom(typeof(Imported), export.Imported);
333         }
334 
335         public class Imported { }
336 
337         public class BaseWithImport
338         {
339             public virtual Imported Imported { get; set; }
340         }
341 
342         public class DerivedFromBaseWithImport : BaseWithImport { }
343 
344         [Fact]
345         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_ExportConventionsWithInheritedProperties_Success()346         public void CreateContainer_ExportConventionsWithInheritedProperties_Success()
347         {
348             var conventions = new ConventionBuilder();
349             conventions.ForType<DerivedFromBaseWithExport>()
350                 .ExportProperty(b => b.Exported);
351 
352             CompositionHost container = new ContainerConfiguration()
353                 .WithDefaultConventions(conventions)
354                 .WithParts(typeof(DerivedFromBaseWithExport))
355                 .CreateContainer();
356             Assert.Equal("A", container.GetExport<string>());
357         }
358 
359         public class BaseWithExport
360         {
361             public string Exported { get { return "A"; } }
362         }
363 
364         public class DerivedFromBaseWithExport : BaseWithExport { }
365 
366         [Fact]
367         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_ExportsToInheritedProperties_DontInterfereWithBase()368         public void CreateContainer_ExportsToInheritedProperties_DontInterfereWithBase()
369         {
370             var conventions = new ConventionBuilder();
371             conventions.ForType<DerivedFromBaseWithExport2>()
372                 .ExportProperty(b => b.Exported);
373 
374             CompositionHost container = new ContainerConfiguration()
375                 .WithDefaultConventions(conventions)
376                 .WithParts(typeof(BaseWithExport2))
377                 .WithParts(typeof(DerivedFromBaseWithExport2))
378                 .CreateContainer();
379             Assert.Equal(new string[] { "A", "A" }, container.GetExports<string>());
380         }
381 
382         public class BaseWithExport2
383         {
384             [Export]
385             public virtual string Exported => "A";
386         }
387 
388         public class DerivedFromBaseWithExport2 : BaseWithExport { }
389 
390         [Fact]
391         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_HasConventions_ClassExportsAreNotInherited()392         public void CreateContainer_HasConventions_ClassExportsAreNotInherited()
393         {
394             CompositionHost container = new ContainerConfiguration()
395                 .WithPart<DerivedFromBaseWithDeclaredExports>(new ConventionBuilder())
396                 .CreateContainer();
397             Assert.False(container.TryGetExport(out BaseWithDeclaredExports export));
398         }
399 
400         [Fact]
401         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_HasConventions_PropertyExportsAreNotInherited()402         public void CreateContainer_HasConventions_PropertyExportsAreNotInherited()
403         {
404             CompositionHost container = new ContainerConfiguration()
405                 .WithPart<DerivedFromBaseWithDeclaredExports>(new ConventionBuilder())
406                 .CreateContainer();
407             Assert.False(container.TryGetExport(out string export));
408         }
409 
410         [Export]
411         public class BaseWithDeclaredExports
412         {
BaseWithDeclaredExports()413             public BaseWithDeclaredExports() => Property = "foo";
414 
415             [Export]
416             public string Property { get; set; }
417         }
418 
419         public class DerivedFromBaseWithDeclaredExports : BaseWithDeclaredExports { }
420 
421         public class CustomExport : ExportAttribute { }
422 
423         [Fact]
424         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_HasConventions_CustomAttributesAreNotInherited()425         public void CreateContainer_HasConventions_CustomAttributesAreNotInherited()
426         {
427             CompositionHost container = new ContainerConfiguration()
428                 .WithPart<DerivedFromBaseWithCustomExport>(new ConventionBuilder())
429                 .CreateContainer();
430             Assert.False(container.TryGetExport(out BaseWithCustomExport bce));
431         }
432 
433         [CustomExport]
434         public class BaseWithCustomExport { }
435 
436         public class DerivedFromBaseWithCustomExport : BaseWithCustomExport { }
437 
438         [Fact]
439         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_OpenGenericTypePart_Success()440         public void CreateContainer_OpenGenericTypePart_Success()
441         {
442             ContainerConfiguration configuration = new ContainerConfiguration().WithParts(typeof(GenericExportedType<>));
443             CompositionHost container = configuration.CreateContainer();
444 
445             Assert.Equal("C", container.GetExport<GenericExportedType<int>>().Property);
446         }
447 
448         [Export(typeof(GenericExportedType<>))]
449         public class GenericExportedType<T>
450         {
451             public string Property => "C";
452         }
453 
454         [Theory]
455         [InlineData(typeof(IncompatibleGenericExportedType<>))]
456         [InlineData(typeof(IncompatibleGenericExportedType<int>))]
457         [InlineData(typeof(IncompatibleGenericExportedTypeDerived<>))]
CreateContainer_GenericTypeExport_ThrowsCompositionFailedException(Type partType)458         public void CreateContainer_GenericTypeExport_ThrowsCompositionFailedException(Type partType)
459         {
460             ContainerConfiguration configuration = new ContainerConfiguration().WithParts(partType);
461             Assert.Throws<CompositionFailedException>(  () => configuration.CreateContainer());
462         }
463 
464         [Export(typeof(GenericExportedType<>))]
465         public class IncompatibleGenericExportedType<T> { }
466 
467         [Export(typeof(GenericExportedType<>))]
468         public class IncompatibleGenericExportedTypeDerived<T> : GenericExportedType<int> { }
469 
470         [Theory]
471         [InlineData(typeof(NonGenericExportedType<>))]
472         [InlineData(typeof(NonGenericExportedType<int>))]
CreateContainer_NonGenericTypeExportWithGenericPart_ThrowsCompositionFailedException(Type partType)473         public void CreateContainer_NonGenericTypeExportWithGenericPart_ThrowsCompositionFailedException(Type partType)
474         {
475             ContainerConfiguration configuration = new ContainerConfiguration().WithParts(partType);
476             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
477         }
478 
479         [Export(typeof(string))]
480         public class NonGenericExportedType<T> { }
481 
482         [Fact]
CreateContainer_UnassignableType_ThrowsCompositionFailedException()483         public void CreateContainer_UnassignableType_ThrowsCompositionFailedException()
484         {
485             ContainerConfiguration configuration = new ContainerConfiguration().WithParts(typeof(ContractExportedType));
486             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
487         }
488 
489         [Export(typeof(Derived))]
490         public class ContractExportedType { }
491 
492         [Fact]
493         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_AbstractOrStructType_Success()494         public void CreateContainer_AbstractOrStructType_Success()
495         {
496             ContainerConfiguration configuration = new ContainerConfiguration().WithParts(typeof(AbstractClass), typeof(StructType));
497             CompositionHost container = configuration.CreateContainer();
498 
499             Assert.Throws<CompositionFailedException>(() => container.GetExport<AbstractClass>());
500             Assert.Throws<CompositionFailedException>(() => container.GetExport<StructType>());
501         }
502 
503         public abstract class AbstractClass { }
504         public struct StructType { }
505 
506         [Fact]
507         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_MetadataProperty_Success()508         public void CreateContainer_MetadataProperty_Success()
509         {
510             ContainerConfiguration configuration = new ContainerConfiguration().WithPart(typeof(MetadataProperty));
511             CompositionHost container = configuration.CreateContainer();
512 
513             Assert.Throws<CompositionFailedException>(() => container.GetExport<MetadataProperty>());
514         }
515 
516         [MetadataAttribute]
517         public class CustomMetadataExportAttribute : ExportAttribute
518         {
519             public object NullName { get; set; } = null;
520             public string StringName { get; set; } = "value";
521             public int[] ArrayName { get; set; } = new int[] { 1, 2, 3 };
522         }
523 
524         public class MetadataProperty
525         {
526             [CustomMetadataExport]
527             [ExportMetadata("NullName", null)]
528             public object NullMetadata { get; set; }
529 
530             [CustomMetadataExport]
531             [ExportMetadata("StringName", "value")]
532             public string StringMetadata { get; set; }
533 
534             [CustomMetadataExport]
535             [ExportMetadata("ArrayName", 4)]
536             public int[] ArrayMetadata { get; set; }
537 
538             [CustomMetadataExport]
539             [ExportMetadata("NewName", 1)]
540             [Required]
541             public int NewMetadata { get; set; }
542         }
543 
544         [Fact]
545         [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)]
CreateContainer_MetadataClass_Success()546         public void CreateContainer_MetadataClass_Success()
547         {
548             ContainerConfiguration configuration = new ContainerConfiguration().WithPart(typeof(MetadataClass));
549             CompositionHost container = configuration.CreateContainer();
550 
551             Assert.Throws<CompositionFailedException>(() => container.GetExport<MetadataProperty>());
552         }
553 
554         [CustomMetadataExport]
555         public class MetadataClass { }
556 
557         [Fact]
CreateContainer_ExportIncompatibleNonGenericProperty_ThrowsCompositionFailedException()558         public void CreateContainer_ExportIncompatibleNonGenericProperty_ThrowsCompositionFailedException()
559         {
560             ContainerConfiguration configuration = new ContainerConfiguration().WithPart(typeof(IncompatibleExportProperty));
561             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
562         }
563 
564         public class IncompatibleExportProperty
565         {
566             [Export(typeof(int))]
567             public string Property { get; set; }
568         }
569 
570         [Fact]
CreateContainer_ExportGenericProperty_Success()571         public void CreateContainer_ExportGenericProperty_Success()
572         {
573             ContainerConfiguration configuration = new ContainerConfiguration().WithPart(typeof(GenericExportProperty<>));
574             Assert.NotNull(configuration.CreateContainer());
575         }
576 
577         public class GenericExportProperty<T>
578         {
579             [Export(typeof(List<>))]
580             public List<T> Property { get; set; } = new List<T>();
581         }
582 
583         [Fact]
CreateContainer_ExportIncompatibleGenericProperty_ThrowsCompositionFailedException()584         public void CreateContainer_ExportIncompatibleGenericProperty_ThrowsCompositionFailedException()
585         {
586             ContainerConfiguration configuration = new ContainerConfiguration().WithPart(typeof(IncompatibleGenericExportProperty<>));
587             Assert.Throws<CompositionFailedException>(() => configuration.CreateContainer());
588         }
589 
590         public class IncompatibleGenericExportProperty<T>
591         {
592             [Export(typeof(List<string>))]
593             public List<T> Property { get; set; }
594         }
595 
DebuggerAttributes_TestData()596         public static IEnumerable<object[]> DebuggerAttributes_TestData()
597         {
598             yield return new object[] { new ContainerConfiguration() };
599             yield return new object[] { new ContainerConfiguration().WithPart(typeof(int)) };
600             yield return new object[] { new ContainerConfiguration().WithDefaultConventions(new ConventionBuilder()).WithPart(typeof(int)) };
601             yield return new object[] { new ContainerConfiguration().WithPart(typeof(int), new ConventionBuilder()) };
602             yield return new object[] { new ContainerConfiguration().WithPart(typeof(ExportedProperty)) };
603         }
604 
605         [Theory]
606         [MemberData(nameof(DebuggerAttributes_TestData))]
607         [SkipOnTargetFramework(TargetFrameworkMonikers.UapAot, "Cannot do DebuggerAttribute testing on UapAot: requires internal Reflection on framework types.")]
DebuggerAttributes_GetViaReflection_Success(ContainerConfiguration configuration)608         public void DebuggerAttributes_GetViaReflection_Success(ContainerConfiguration configuration)
609         {
610             DebuggerAttributeInfo debuggerAttributeInfo = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(configuration);
611             foreach (PropertyInfo property in debuggerAttributeInfo.Properties)
612             {
613                 Assert.NotNull(property.GetValue(debuggerAttributeInfo.Instance));
614             }
615         }
616     }
617 }
618