Adding custom attributes using mono.cecil?
It's actually very easy.
ModuleDefinition module = ...;
MethodDefinition targetMethod = ...;
MethodReference attributeConstructor = module.Import(
typeof(DebuggerHiddenAttribute).GetConstructor(Type.EmptyTypes));
targetMethod.CustomAttributes.Add(new CustomAttribute(attributeConstructor));
module.Write(...);
This is my take,
MethodDefinition methodDefinition = ...;
var module = methodDefinition.DeclaringType.Module;
var attr = module.Import(typeof (System.Diagnostics.DebuggerHiddenAttribute));
var attrConstructor = attr.Resolve().Constructors.GetConstructor(false, new Type[] {});
methodDefinition.CustomAttributes.Add(new CustomAttribute(attrConstructor));
I noticed Jb Evain's snippet is slightly different. I'm not sure whether that is because is because he's using a newer version of Cecil or because I'm wrong :)
In my version of Cecil, Import
returns a TypeReference
, not the constructor.
I want to elaborate on Jb Evain's answer, about how to pass parameters to the attribute. For the sample, I used System.ComponentModel.BrowsableAttribute
and passed the vlaue of browsable
parameter to its constructor:
void AddBrowsableAttribute(
ModuleDefinition module,
Mono.Cecil.ICustomAttributeProvider targetMember, // Can be a PropertyDefinition, MethodDefinition or other member definitions
bool browsable)
{
// Your attribute type
var attribType = typeof(System.ComponentModel.BrowsableAttribute);
// Find your required constructor. This one has one boolean parameter.
var constructor = attribType.GetConstructors()[0];
var constructorRef = module.ImportReference(constructor);
var attrib = new CustomAttribute(constructorRef);
// The argument
var browsableArg =
new CustomAttributeArgument(
module.ImportReference(typeof(bool)),
browsable);
attrib.ConstructorArguments.Add(browsableArg);
targetMember.CustomAttributes.Add(attrib);
}
Also, named arguments can be added to Properties
collection of the created CustomAttribute
.