On Wed, Feb 22, 2012 at 8:09 PM, thargy <uncle...@googlemail.com> wrote:
> I have the CustomAttributes, and I believe I need to use
> Constructor.Paramter.Add(), however, Constructor.Parameter is null in
> the case there are no parameters already.
If you have a CustomAttribute.ConstructorParameters collection, it
means that you're using an old version of Mono.Cecil. I strongly
suggest you use a recent one from http://github.com/jbevain/cecil.
If you have a CustomAttribute.ConstructorArguments collections, you're good.
And if you want to set properties, you can not use constructor
arguments. Remember that a custom attributes is mapped to a
constructor invocation, plus setting some fields and properties. So in
your example, AttachDataAttribute has default constructor with no
parameter, and thus, no argument is passed to instantiate it.
What you want to do, representing [AttachData(Type =
typeof(Foo.Bar))], is setting a value through a property of a custom
attribute.
You can do it with something like:
var module = ... as ModuleDefinition;
var attachData = new CustomAttribute (module.Import (theAttachDataConstructor));
var value = module.Import (fooBar); // create a reference to Foo.Bar
scoped for module
var type = module.Import (typeof (Type)); // create a reference to
System.Type scoped for module
/*
the issue with using typeof (Type) is that it will create a reference
to the version of System.Type your CLR is running on
so if you're instrumenting a 2.0 assembly from a 4.0 program, you
better pass a Cecil representation of the 2.0 System.Type
*/
attachData.Properties.Add (new CustomAttributeNamedArgument ("Type",
new CustomAttributeArgument (type, value)));
The code is not guaranteed to be exact and is written from memory.
Jb
I actually did. Cecil 0.6 has a ConstructorParameters collection that
was renamed in 0.9, hence the confusion.
CustomAttribute.Constructor.Parameters actually point to the
parameters of the constructors. You don't want to modify that unless
you want to modify the constructor of say, AttachDataAttribute.
> I'm not trying to add a new Attribute, I'm trying to modify an
> existing attribute in the assembly (as per example).
The principle is the same, instead of creating a new one, you can just
modify an existing one. You can add a CustomAttributeNamedArgument in
the Properties, and if everything is correct, it will be serialized at
Write time.
> Further to previous question, I get the type by resolving the
> module.TypeSystem.CorLib to an AssemblyDefinition and using GetType on
> the MainModule, this guarantees I get the type from the right
> framework library and avoid creating a dependency on the Type in the
> framework currently being used.
This work too.
> To come back to my problem, is the only way to remove the existing
> attribute and add a new one, or is it possible to do this on an
> existing attribute?
It shouldn't be a problem to modify an existing one.
Jb