Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add a custom attribute without a default constructor using mono.cecil

Tags:

c#

mono.cecil

This question is related to this one, but is not a duplicate. Jb posted there that to add a custom attribute, the following snippet would work:

ModuleDefinition module = ...;
MethodDefinition targetMethod = ...;
MethodReference attributeConstructor = module.Import(
    typeof(DebuggerHiddenAttribute).GetConstructor(Type.EmptyTypes));

targetMethod.CustomAttributes.Add(new CustomAttribute(attributeConstructor));
module.Write(...);

I would like to use something similar, but to add a custom attribute whose constructor takes two string parameters in its (only) constructor, and I'd like to specify values for those (obviously). Can anyone help?

like image 448
David M Avatar asked Apr 23 '12 13:04

David M


2 Answers

First you have to get a reference to the proper version of the constructor:

MethodReference attributeConstructor = module.Import(
    typeof(MyAttribute).GetConstructor(new [] { typeof(string), typeof(string) }));

Then you can simply populate the custom attributes with string arguments:

CustomAttribute attribute = new CustomAttribute(attributeConstructor);
attribute.ConstructorArguments.Add(
        new CustomAttributeArgument(
            module.TypeSystem.String, "Foo"));
attribute.ConstructorArguments.Add(
        new CustomAttributeArgument(
            module.TypeSystem.String, "Bar"));
like image 169
Jb Evain Avatar answered Sep 22 '22 17:09

Jb Evain


Here's how to set Named Parameters of a custom attribute which totally bypasses the setting of an attribute value using it's constructors. As a note you can't set the CustomAttributeNamedArgument.Argument.Value or even CustomAttributeNamedArgument.Argument directly as they are readonly.

The following is equivalent to setting - [XXX(SomeNamedProperty = {some value})]

    var attribDefaultCtorRef = type.Module.Import(typeof(XXXAttribute).GetConstructor(Type.EmptyTypes));
    var attrib = new CustomAttribute(attribDefaultCtorRef);
    var namedPropertyTypeRef = type.Module.Import(typeof(YYY));
    attrib.Properties.Add(new CustomAttributeNamedArgument("SomeNamedProperty", new CustomAttributeArgument(namedPropertyTypeRef, {some value})));
    method.CustomAttributes.Add(attrib);
like image 40
Rohit Avatar answered Sep 24 '22 17:09

Rohit