Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding custom attributes using mono.cecil?

Tags:

c#

mono.cecil

I can't figure how to add custom attribute to a method using Mono.Cecil The attributes that I would want to add is like this :

.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) 

Does anyone know how to add custom attributes

like image 858
method Avatar asked Dec 05 '11 16:12

method


3 Answers

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(...);
like image 156
Jb Evain Avatar answered Nov 12 '22 19:11

Jb Evain


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.

like image 4
sehe Avatar answered Nov 12 '22 18:11

sehe


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.

like image 1
Mohammad Dehghan Avatar answered Nov 12 '22 18:11

Mohammad Dehghan