/
MefLanguageServices.cs
64 lines (51 loc) · 2.04 KB
/
MefLanguageServices.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
// Copyright (c) .NET Foundation and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Host;
namespace Roslynator.Host.Mef;
internal class MefLanguageServices
{
private readonly ImmutableArray<Lazy<ILanguageService, LanguageServiceMetadata>> _services;
private ImmutableDictionary<Type, Lazy<ILanguageService, LanguageServiceMetadata>?> _serviceMap
= ImmutableDictionary<Type, Lazy<ILanguageService, LanguageServiceMetadata>?>.Empty;
public MefLanguageServices(
MefWorkspaceServices workspaceServices,
string language)
{
WorkspaceServices = workspaceServices;
Language = language;
_services = workspaceServices.GetExports<ILanguageService, LanguageServiceMetadata>()
.Where(lazy => lazy.Metadata.Language == language)
.ToImmutableArray();
}
public MefWorkspaceServices WorkspaceServices { get; }
public string Language { get; }
public bool HasServices => _services.Length > 0;
public TLanguageService? GetService<TLanguageService>()
{
if (TryGetService(typeof(TLanguageService), out Lazy<ILanguageService, LanguageServiceMetadata>? service))
{
return (TLanguageService)service!.Value;
}
else
{
return default;
}
}
internal bool TryGetService(Type serviceType, out Lazy<ILanguageService, LanguageServiceMetadata>? service)
{
if (!_serviceMap.TryGetValue(serviceType, out service))
{
service = ImmutableInterlocked.GetOrAdd(
ref _serviceMap,
serviceType,
type =>
{
string fullName = type.AssemblyQualifiedName;
return _services.SingleOrDefault(lz => lz.Metadata.ServiceType == fullName, shouldThrow: false);
});
}
return service != default;
}
}