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; 6 using System.Collections.Generic; 7 using System.ComponentModel; 8 using System.Composition.Hosting; 9 using System.Composition.UnitTests.Util; 10 using System.Linq; 11 using System.Text; 12 using System.Threading.Tasks; 13 using Xunit; 14 15 namespace System.Composition.Lightweight.UnitTests 16 { 17 public class MetadataViewGenerationTests 18 { 19 [Export, ExportMetadata("Name", "A")] 20 public class HasNameA { } 21 22 public class Named { public string Name { get; set; } } 23 24 [Fact] 25 [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)] AConcreteTypeWithWritablePropertiesIsAMetadataView()26 public void AConcreteTypeWithWritablePropertiesIsAMetadataView() 27 { 28 var cc = new ContainerConfiguration() 29 .WithPart<HasNameA>() 30 .CreateContainer(); 31 32 var hn = cc.GetExport<Lazy<HasNameA, Named>>(); 33 34 Assert.Equal("A", hn.Metadata.Name); 35 } 36 37 [Export] 38 public class HasNoName { } 39 40 public class OptionallyNamed {[DefaultValue("B")] public string Name { get; set; } } 41 42 [Fact] 43 [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)] MetadataViewsCanCarryDefaultValues()44 public void MetadataViewsCanCarryDefaultValues() 45 { 46 var cc = new ContainerConfiguration() 47 .WithPart<HasNoName>() 48 .CreateContainer(); 49 50 var hn = cc.GetExport<Lazy<HasNoName, OptionallyNamed>>(); 51 52 Assert.Equal("B", hn.Metadata.Name); 53 } 54 55 public class DictionaryName 56 { DictionaryName(IDictionary<string, object> metadata)57 public DictionaryName(IDictionary<string, object> metadata) 58 { 59 RetrievedName = (string)metadata["Name"]; 60 } 61 62 public string RetrievedName { get; set; } 63 } 64 65 [Fact] 66 [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)] AConcreteTypeWithDictionaryConstructorIsAMetadataView()67 public void AConcreteTypeWithDictionaryConstructorIsAMetadataView() 68 { 69 var cc = new ContainerConfiguration() 70 .WithPart<HasNameA>() 71 .CreateContainer(); 72 73 var hn = cc.GetExport<Lazy<HasNameA, DictionaryName>>(); 74 75 Assert.Equal("A", hn.Metadata.RetrievedName); 76 } 77 78 public class InvalidConcreteView 79 { InvalidConcreteView(string unsupported)80 public InvalidConcreteView(string unsupported) { } 81 } 82 83 [Fact] 84 [ActiveIssue("https://github.com/dotnet/corefx/issues/20656", TargetFrameworkMonikers.UapAot)] 85 [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)] AConcreteTypeWithUnsupportedConstructorsCannotBeUsedAsAMetadataView()86 public void AConcreteTypeWithUnsupportedConstructorsCannotBeUsedAsAMetadataView() 87 { 88 var cc = new ContainerConfiguration() 89 .WithPart<HasNameA>() 90 .CreateContainer(); 91 92 var x = Assert.Throws<CompositionFailedException>(() => cc.GetExport<Lazy<HasNoName, InvalidConcreteView>>()); 93 94 Assert.Equal("The type 'InvalidConcreteView' cannot be used as a metadata view. A metadata view must be a concrete class with a parameterless or dictionary constructor.", x.Message); 95 } 96 97 [Export, ExportMetadata("Name", "A")] 98 public class ExportsWithMetadata { } 99 100 public interface INamed { string Name { get; } } 101 102 [Export] 103 public class ImportsWithMetadataInterface 104 { 105 [Import] 106 public Lazy<ExportsWithMetadata, INamed> Imported { get; set; } 107 } 108 109 [Fact] 110 [ActiveIssue("https://github.com/dotnet/corefx/issues/20656", TargetFrameworkMonikers.UapAot)] 111 [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)] UnsupportedMetadataViewMessageIsInformative()112 public void UnsupportedMetadataViewMessageIsInformative() 113 { 114 var cc = new ContainerConfiguration().WithParts(typeof(ImportsWithMetadataInterface), typeof(ExportsWithMetadata)).CreateContainer(); 115 var x = Assert.Throws<CompositionFailedException>(() => cc.GetExport<ImportsWithMetadataInterface>()); 116 Assert.Equal("The type 'INamed' cannot be used as a metadata view. A metadata view must be a concrete class with a parameterless or dictionary constructor.", x.Message); 117 } 118 119 public class ReadonlyNameOrderMetadata 120 { 121 public int Order { get; set; } 122 public string Name { get { return "Name"; } } 123 } 124 125 [Export, ExportMetadata("Order", 1)] 126 public class HasOrder { } 127 128 [Fact] 129 [ActiveIssue(24903, TargetFrameworkMonikers.NetFramework)] ReadOnlyPropertiesOnMetadataViewsAreIgnored()130 public void ReadOnlyPropertiesOnMetadataViewsAreIgnored() 131 { 132 var c = new ContainerConfiguration() 133 .WithPart<HasOrder>() 134 .CreateContainer(); 135 136 var l = c.GetExport<Lazy<HasOrder, ReadonlyNameOrderMetadata>>(); 137 Assert.Equal(1, l.Metadata.Order); 138 } 139 } 140 } 141