Created
October 2, 2009 11:10
-
-
Save jbevain/199666 to your computer and use it in GitHub Desktop.
A tool to rewrite generic constraints for enums and delegates
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 System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using SR = System.Reflection; | |
using Mono.Cecil; | |
class Program { | |
const string delegate_constraint = "DelegateConstraintAttribute"; | |
const string enum_constraint = "EnumConstraintAttribute"; | |
static void Main (string [] args) | |
{ | |
if (args.Length == 0) | |
Usage (); | |
var assembly_file = args [0]; | |
if (!File.Exists (assembly_file)) | |
Usage (); | |
var key_pair_file = args.Length > 1 && File.Exists (args [1]) ? args [1] : null; | |
var key_pair = key_pair_file != null ? new SR.StrongNameKeyPair (key_pair_file) : null; | |
var module = ModuleDefinition.ReadModule (assembly_file); | |
ProcessModule (module); | |
var attributes = new [] {delegate_constraint, enum_constraint}; | |
foreach (var attribute in attributes) { | |
var type = module.Types [attribute]; | |
if (type != null) | |
module.Types.Remove (type); | |
} | |
module.Write (args [0], new WriterParameters { | |
StrongNameKeyPair = key_pair, | |
}); | |
} | |
static void ProcessModule (ModuleDefinition module) | |
{ | |
foreach (var type in module.Types) { | |
Process (type); | |
if (!type.HasMethods) | |
continue; | |
foreach (var method in type.Methods) | |
Process (method); | |
} | |
} | |
static void Process (IGenericParameterProvider provider) | |
{ | |
if (!provider.HasGenericParameters) | |
return; | |
foreach (var parameter in provider.GenericParameters) | |
Process (parameter); | |
} | |
static void Process (GenericParameter generic_parameter) | |
{ | |
if (!generic_parameter.HasCustomAttributes) | |
return; | |
var custom_attributes = generic_parameter.CustomAttributes; | |
for (int i = 0; i < custom_attributes.Count; i++) { | |
var attribute = custom_attributes [i]; | |
if (IsDelegateConstraintAttribute (attribute)) { | |
generic_parameter.Attributes &= ~GenericParameterAttributes.ReferenceTypeConstraint; | |
generic_parameter.Constraints.Insert (0, CreateConstraint ("System", "Delegate", generic_parameter)); | |
custom_attributes.RemoveAt (i--); | |
} else if (IsEnumConstraintAttribute (attribute)) { | |
generic_parameter.Attributes &= ~GenericParameterAttributes.NotNullableValueTypeConstraint; | |
generic_parameter.Constraints.Insert (0, CreateConstraint ("System", "Enum", generic_parameter)); | |
custom_attributes.RemoveAt (i--); | |
} | |
} | |
} | |
static TypeReference CreateConstraint (string @namespace, string name, GenericParameter generic_parameter) | |
{ | |
var module = generic_parameter.Module; | |
var corlib = module.AssemblyReferences.First (a => a.Name == "mscorlib"); | |
return new TypeReference (@namespace, name, corlib, false); | |
} | |
static bool IsDelegateConstraintAttribute (CustomAttribute attribute) | |
{ | |
return IsConstraintAttribute ("DelegateConstraintAttribute", attribute); | |
} | |
static bool IsEnumConstraintAttribute (CustomAttribute attribute) | |
{ | |
return IsConstraintAttribute ("EnumConstraintAttribute", attribute); | |
} | |
static bool IsConstraintAttribute (string type, CustomAttribute attribute) | |
{ | |
return attribute.Constructor.DeclaringType.Name == type; | |
} | |
static void Usage () | |
{ | |
Console.WriteLine ("patch-constraints assembly [keypair.snk]"); | |
Environment.Exit (1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment