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