-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
MetadataReaderExtensions.cs
91 lines (80 loc) · 3.23 KB
/
MetadataReaderExtensions.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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Reflection;
using System.Reflection.Metadata;
using Microsoft.CodeAnalysis;
namespace Microsoft.NET.Sdk.Razor.Tool
{
internal static class MetadataReaderExtensions
{
internal static AssemblyIdentity GetAssemblyIdentity(this MetadataReader reader)
{
if (!reader.IsAssembly)
{
throw new BadImageFormatException();
}
var definition = reader.GetAssemblyDefinition();
return CreateAssemblyIdentity(
reader,
definition.Version,
definition.Flags,
definition.PublicKey,
definition.Name,
definition.Culture,
isReference: false);
}
internal static AssemblyIdentity[] GetReferencedAssembliesOrThrow(this MetadataReader reader)
{
var references = new List<AssemblyIdentity>(reader.AssemblyReferences.Count);
foreach (var referenceHandle in reader.AssemblyReferences)
{
var reference = reader.GetAssemblyReference(referenceHandle);
references.Add(CreateAssemblyIdentity(
reader,
reference.Version,
reference.Flags,
reference.PublicKeyOrToken,
reference.Name,
reference.Culture,
isReference: true));
}
return references.ToArray();
}
private static AssemblyIdentity CreateAssemblyIdentity(
MetadataReader reader,
Version version,
AssemblyFlags flags,
BlobHandle publicKey,
StringHandle name,
StringHandle culture,
bool isReference)
{
var publicKeyOrToken = reader.GetBlobContent(publicKey);
bool hasPublicKey;
if (isReference)
{
hasPublicKey = (flags & AssemblyFlags.PublicKey) != 0;
}
else
{
// Assembly definitions never contain a public key token, they only can have a full key or nothing,
// so the flag AssemblyFlags.PublicKey does not make sense for them and is ignored.
// See Ecma-335, Partition II Metadata, 22.2 "Assembly : 0x20".
// This also corresponds to the behavior of the native C# compiler and sn.exe tool.
hasPublicKey = !publicKeyOrToken.IsEmpty;
}
if (publicKeyOrToken.IsEmpty)
{
publicKeyOrToken = default;
}
return new AssemblyIdentity(
name: reader.GetString(name),
version: version,
cultureName: culture.IsNil ? null : reader.GetString(culture),
publicKeyOrToken: publicKeyOrToken,
hasPublicKey: hasPublicKey,
isRetargetable: (flags & AssemblyFlags.Retargetable) != 0,
contentType: (AssemblyContentType)((int)(flags & AssemblyFlags.ContentTypeMask) >> 9));
}
}
}