forked from dotnet/format
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ExportProviderExtensions.cs
105 lines (94 loc) · 5.07 KB
/
ExportProviderExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting.Core;
using System.Linq;
using System.Reflection;
using Microsoft.VisualStudio.Composition;
namespace Microsoft.CodeAnalysis.Tools.Tests
{
internal static class ExportProviderExtensions
{
public static CompositionContext AsCompositionContext(this ExportProvider exportProvider)
{
return new CompositionContextShim(exportProvider);
}
private class CompositionContextShim : CompositionContext
{
private readonly ExportProvider _exportProvider;
public CompositionContextShim(ExportProvider exportProvider)
{
_exportProvider = exportProvider;
}
public override bool TryGetExport(CompositionContract contract, out object export)
{
var importMany = contract.MetadataConstraints.Contains(new KeyValuePair<string, object>("IsImportMany", true));
var (contractType, metadataType, isArray) = GetContractType(contract.ContractType, importMany);
if (metadataType != null)
{
var methodInfo = (from method in _exportProvider.GetType().GetTypeInfo().GetMethods()
where method.Name == nameof(ExportProvider.GetExports)
where method.IsGenericMethod && method.GetGenericArguments().Length == 2
where method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType == typeof(string)
select method).Single();
var parameterizedMethod = methodInfo.MakeGenericMethod(contractType, metadataType);
export = parameterizedMethod.Invoke(_exportProvider, new[] { contract.ContractName });
}
else if (!isArray)
{
var methodInfo = (from method in _exportProvider.GetType().GetTypeInfo().GetMethods()
where method.Name == nameof(ExportProvider.GetExports)
where method.IsGenericMethod && method.GetGenericArguments().Length == 1
where method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType == typeof(string)
select method).Single();
var parameterizedMethod = methodInfo.MakeGenericMethod(contractType);
export = parameterizedMethod.Invoke(_exportProvider, new[] { contract.ContractName });
}
else
{
var methodInfo = (from method in _exportProvider.GetType().GetTypeInfo().GetMethods()
where method.Name == nameof(ExportProvider.GetExportedValues)
where method.IsGenericMethod && method.GetGenericArguments().Length == 1
where method.GetParameters().Length == 0
select method).Single();
var parameterizedMethod = methodInfo.MakeGenericMethod(contractType);
export = parameterizedMethod.Invoke(_exportProvider, null);
}
return true;
}
private (Type exportType, Type metadataType, bool isArray) GetContractType(Type contractType, bool importMany)
{
if (importMany && contractType.BaseType == typeof(Array))
{
return (contractType.GetElementType(), null, true);
}
if (importMany && contractType.IsConstructedGenericType)
{
if (contractType.GetGenericTypeDefinition() == typeof(IList<>)
|| contractType.GetGenericTypeDefinition() == typeof(ICollection<>)
|| contractType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
contractType = contractType.GenericTypeArguments[0];
}
}
if (contractType.IsConstructedGenericType)
{
if (contractType.GetGenericTypeDefinition() == typeof(Lazy<>))
{
return (contractType.GenericTypeArguments[0], null, false);
}
else if (contractType.GetGenericTypeDefinition() == typeof(Lazy<,>))
{
return (contractType.GenericTypeArguments[0], contractType.GenericTypeArguments[1], false);
}
else
{
throw new NotSupportedException();
}
}
throw new NotSupportedException();
}
}
}
}