-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAssemblyPublicizer.cs
More file actions
130 lines (105 loc) · 4.37 KB
/
AssemblyPublicizer.cs
File metadata and controls
130 lines (105 loc) · 4.37 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using Mono.Cecil;
namespace QuickAssemblyPublicizer;
public sealed class AssemblyPublicizer
{
private readonly ILogger _logger;
public AssemblyPublicizer(ILogger logger)
{
this._logger = logger;
}
public void Publicize(string inputFilePath, string outputFilePath)
{
try
{
var assemblyResolver = new DefaultAssemblyResolver();
assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(inputFilePath) ?? ".");
var readSymbols = ShouldReadSymbols(inputFilePath);
var readerParameters = new ReaderParameters
{
ReadSymbols = readSymbols,
ThrowIfSymbolsAreNotMatching = false,
AssemblyResolver = assemblyResolver
};
using var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputFilePath, readerParameters);
MakeScopePublic(assemblyDefinition.MainModule);
var writerParameters = new WriterParameters { WriteSymbols = assemblyDefinition.MainModule.HasSymbols };
assemblyDefinition.Write(outputFilePath, writerParameters);
_logger.Info($"Publicized '{inputFilePath}' -> '{outputFilePath}'");
}
catch (AssemblyResolutionException exception)
{
_logger.Warn($"Could not resolve reference '{exception.AssemblyReference.FullName}' - continuing anyway");
var assemblyResolver = new DefaultAssemblyResolver();
assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(inputFilePath) ?? ".");
var readerParameters = new ReaderParameters
{
ReadSymbols = false,
ThrowIfSymbolsAreNotMatching = false,
AssemblyResolver = assemblyResolver,
ReadingMode = ReadingMode.Deferred
};
using var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputFilePath, readerParameters);
MakeScopePublic(assemblyDefinition.MainModule);
var writerParameters = new WriterParameters { WriteSymbols = false };
assemblyDefinition.Write(outputFilePath, writerParameters);
_logger.Info($"Publicized '{inputFilePath}' -> '{outputFilePath}'");
}
}
private static bool ShouldReadSymbols(string inputFilePath)
{
var pdbFilePath = Path.ChangeExtension(inputFilePath, ".pdb");
return File.Exists(pdbFilePath);
}
private static void MakeScopePublic(ModuleDefinition module)
{
foreach (var typeDefinition in module.Types)
{
if (typeDefinition.Name == "<Module>")
{
continue;
}
MakeTypePublic(typeDefinition);
}
}
private static void MakeTypePublic(TypeDefinition typeDefinition)
{
typeDefinition.Attributes = typeDefinition.IsNested
? (typeDefinition.Attributes & ~TypeAttributes.VisibilityMask) | TypeAttributes.NestedPublic
: (typeDefinition.Attributes & ~TypeAttributes.VisibilityMask) | TypeAttributes.Public;
foreach (var nestedType in typeDefinition.NestedTypes)
{
MakeTypePublic(nestedType);
}
foreach (var methodDefinition in typeDefinition.Methods)
{
MakeMethodPublic(methodDefinition);
}
foreach (var fieldDefinition in typeDefinition.Fields)
{
MakeFieldPublic(fieldDefinition);
}
foreach (var propertyDefinition in typeDefinition.Properties)
{
MakePropertyPublic(propertyDefinition);
}
}
private static void MakeMethodPublic(MethodDefinition methodDefinition)
{
methodDefinition.Attributes = (methodDefinition.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public;
}
private static void MakeFieldPublic(FieldDefinition fieldDefinition)
{
fieldDefinition.Attributes = (fieldDefinition.Attributes & ~FieldAttributes.FieldAccessMask) | FieldAttributes.Public;
}
private static void MakePropertyPublic(PropertyDefinition propertyDefinition)
{
if (propertyDefinition.GetMethod is not null)
{
MakeMethodPublic(propertyDefinition.GetMethod);
}
if (propertyDefinition.SetMethod is not null)
{
MakeMethodPublic(propertyDefinition.SetMethod);
}
}
}