Last active
January 30, 2018 07:41
-
-
Save jagt/00a86f32fb0652155787cb6356ad5efb to your computer and use it in GitHub Desktop.
publicize.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Mono.Cecil; | |
using System; | |
using System.Linq; | |
using System.Collections.Generic; | |
// inplace publicize all methods/types in a dll | |
// need Mono.Cecil in nuget | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
if (args.Length < 1) | |
{ | |
Console.WriteLine("usage: publicize foo.dll"); | |
Environment.Exit(-1); | |
return; | |
} | |
var dllName = args[0]; | |
var dllDef = AssemblyDefinition.ReadAssembly(dllName); | |
var mainModule = dllDef.MainModule; | |
foreach (var type in mainModule.GetTypes()) | |
{ | |
ProcessType(type); | |
} | |
mainModule.Write(dllName + ".patched"); | |
} | |
static bool IsCompilerGenerated(IEnumerable<CustomAttribute> customAttributes) | |
{ | |
return customAttributes.Any(x => x.AttributeType.Name == "CompilerGeneratedAttribute"); | |
} | |
private static void ProcessType(TypeDefinition typeDefinition) | |
{ | |
if (IsCompilerGenerated(typeDefinition.CustomAttributes)) | |
{ | |
return; | |
} | |
// recur into nested first before any return | |
foreach (var nestedType in typeDefinition.NestedTypes) | |
{ | |
ProcessType(nestedType); | |
} | |
// it's really cool that 'IsNotPublic' and '!IsPublic' are two completely | |
// different things. wow. | |
if (!typeDefinition.IsPublic) | |
{ | |
if (typeDefinition.IsNested) | |
{ | |
typeDefinition.IsNestedPublic = true; | |
} | |
else | |
{ | |
typeDefinition.IsPublic = true; | |
} | |
Console.WriteLine("Publicize class {0}", typeDefinition.Name); | |
} | |
if (typeDefinition.IsInterface) | |
{ | |
return; | |
} | |
foreach (var method in typeDefinition.Methods) | |
{ | |
ProcessMethod(method); | |
} | |
foreach (var field in typeDefinition.Fields) | |
{ | |
ProcessField(field); | |
} | |
} | |
private static void ProcessMethod(MethodDefinition method) | |
{ | |
var requiresPublicize = false; | |
if (method.IsPublic) | |
{ | |
return; | |
} | |
if (method.IsAssembly) | |
{ | |
method.IsAssembly = false; | |
requiresPublicize = true; | |
} | |
if (method.IsHideBySig) | |
{ | |
method.IsHideBySig = false; | |
requiresPublicize = true; | |
} | |
if (method.IsPrivate) | |
{ | |
method.IsPrivate = false; | |
requiresPublicize = true; | |
} | |
if (requiresPublicize) | |
{ | |
method.IsPublic = true; | |
Console.WriteLine("Publicize method {0}", method.Name); | |
} | |
} | |
private static void ProcessField(FieldDefinition field) | |
{ | |
if (IsCompilerGenerated(field.CustomAttributes)) | |
{ | |
return; | |
} | |
if (field.IsPublic) | |
{ | |
return; | |
} | |
var requiresPublicize = false; | |
if (field.IsAssembly) | |
{ | |
field.IsAssembly = false; | |
requiresPublicize = true; | |
} | |
if (field.IsPrivate) | |
{ | |
field.IsPrivate = false; | |
requiresPublicize = true; | |
} | |
if (requiresPublicize) | |
{ | |
field.IsPublic = true; | |
Console.WriteLine("Publicize field {0}", field.Name); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment