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 . Composition ;
8+ using System . Composition . Hosting . Core ;
9+ using System . Linq ;
10+ using System . Reflection ;
11+ using Microsoft . VisualStudio . Composition ;
12+
13+ namespace ICSharpCode . CodeConverter . Util . FromRoslynSdk
14+ {
15+ internal static class ExportProviderExtensions
16+ {
17+ public static CompositionContext AsCompositionContext ( this ExportProvider exportProvider )
18+ {
19+ return new CompositionContextShim ( exportProvider ) ;
20+ }
21+
22+ private class CompositionContextShim : CompositionContext
23+ {
24+ private readonly ExportProvider _exportProvider ;
25+
26+ public CompositionContextShim ( ExportProvider exportProvider )
27+ {
28+ _exportProvider = exportProvider ;
29+ }
30+
31+ public override bool TryGetExport ( CompositionContract contract , out object export )
32+ {
33+ var importMany = contract . MetadataConstraints . Contains ( new KeyValuePair < string , object > ( "IsImportMany" , true ) ) ;
34+ var ( contractType , metadataType ) = GetContractType ( contract . ContractType , importMany ) ;
35+
36+ if ( metadataType != null )
37+ {
38+ var methodInfo = ( from method in _exportProvider . GetType ( ) . GetTypeInfo ( ) . GetMethods ( )
39+ where method . Name == nameof ( ExportProvider . GetExports )
40+ where method . IsGenericMethod && method . GetGenericArguments ( ) . Length == 2
41+ where method . GetParameters ( ) . Length == 1 && method . GetParameters ( ) [ 0 ] . ParameterType == typeof ( string )
42+ select method ) . Single ( ) ;
43+ var parameterizedMethod = methodInfo . MakeGenericMethod ( contractType , metadataType ) ;
44+ export = parameterizedMethod . Invoke ( _exportProvider , new [ ] { contract . ContractName } ) ;
45+ }
46+ else
47+ {
48+ var methodInfo = ( from method in _exportProvider . GetType ( ) . GetTypeInfo ( ) . GetMethods ( )
49+ where method . Name == nameof ( ExportProvider . GetExports )
50+ where method . IsGenericMethod && method . GetGenericArguments ( ) . Length == 1
51+ where method . GetParameters ( ) . Length == 1 && method . GetParameters ( ) [ 0 ] . ParameterType == typeof ( string )
52+ select method ) . Single ( ) ;
53+ var parameterizedMethod = methodInfo . MakeGenericMethod ( contractType ) ;
54+ export = parameterizedMethod . Invoke ( _exportProvider , new [ ] { contract . ContractName } ) ;
55+ }
56+
57+ return true ;
58+ }
59+
60+ private ( Type exportType , Type ? metadataType ) GetContractType ( Type contractType , bool importMany )
61+ {
62+ if ( importMany && contractType . IsConstructedGenericType )
63+ {
64+ if ( contractType . GetGenericTypeDefinition ( ) == typeof ( IList < > )
65+ || contractType . GetGenericTypeDefinition ( ) == typeof ( ICollection < > )
66+ || contractType . GetGenericTypeDefinition ( ) == typeof ( IEnumerable < > ) )
67+ {
68+ contractType = contractType . GenericTypeArguments [ 0 ] ;
69+ }
70+ }
71+
72+ if ( contractType . IsConstructedGenericType )
73+ {
74+ if ( contractType . GetGenericTypeDefinition ( ) == typeof ( Lazy < > ) )
75+ {
76+ return ( contractType . GenericTypeArguments [ 0 ] , null ) ;
77+ }
78+ else if ( contractType . GetGenericTypeDefinition ( ) == typeof ( Lazy < , > ) )
79+ {
80+ return ( contractType . GenericTypeArguments [ 0 ] , contractType . GenericTypeArguments [ 1 ] ) ;
81+ }
82+ else
83+ {
84+ throw new NotSupportedException ( ) ;
85+ }
86+ }
87+
88+ throw new NotSupportedException ( ) ;
89+ }
90+ }
91+ }
92+ }
0 commit comments