6

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?

Community
  • 1
  • 1
David M
  • 71,481
  • 13
  • 158
  • 186

2 Answers2

12

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"));
David M
  • 71,481
  • 13
  • 158
  • 186
Jb Evain
  • 17,319
  • 2
  • 67
  • 67
  • Quick as ever Jb - thanks very much for the help. Too quick for me to accept the answer, which I'll do in a few minutes... – David M Apr 23 '12 at 13:14
  • Google must be indexing SO in real-time: I'm using a simple google alert on Mono.Cecil. – Jb Evain Apr 23 '12 at 13:18
  • 1
    Jb - in case you're interested, the mutation testing framework I'm working on is on Codeplex: http://ninjaturtles.codeplex.com. So far, it's working on IL manipulation only (source code mutation possibly to come) so Mono.Cecil has been an absolute godsend. Thanks for all your hard work on it. – David M Apr 23 '12 at 14:43
  • @DavidM, awesome, I took the liberty to add your project to the list of Cecil users: http://github.com/jbevain/cecil/wiki/Users – Jb Evain Apr 23 '12 at 16:14
  • Thanks Jb, happy to have it there! – David M Apr 23 '12 at 16:31
2

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);
Rohit
  • 51
  • 3