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