Custom Attributes

402 views
Skip to first unread message

Hendry Luk

unread,
Apr 23, 2011, 3:30:48 PM4/23/11
to mono-...@googlegroups.com
Hi,
Is there any easy way in cecil to get a certain custom-attributes (of a specific type) from a method, and execute a virtual method on it?
Just like it can easily be done using a basic System.Reflection.

The only way i can think of is to manually load the assembly containing that attributes (that I've discovered using cecil), then instantiate the attribute using the constructor-arguments information (from cecil), and then copy across all property-values (from cecil). Once you got the attribute instance, I can then execute the method. It seems to be a lot of work for such a _very_ common thing.

Oh while I'm here, is there also an easy way to do type.IsAssignableFrom(type) on cecil? At the moment i'm recursively checking all the base-classes within its ancestry line, as well as their interfaces, but it feels very inefficient, considering it's also a very common thing (checking for types assignability is probably far more common than checking for an exact equality). Is there a better way to do this?

Thanks before

Jb Evain

unread,
Apr 23, 2011, 3:55:14 PM4/23/11
to mono-...@googlegroups.com
Hi,

On Sat, Apr 23, 2011 at 9:30 PM, Hendry Luk <hendr...@gmail.com> wrote:
> Hi,
> Is there any easy way in cecil to get a certain custom-attributes (of a
> specific type) from a method, and execute a virtual method on it?
> Just like it can easily be done using a basic System.Reflection.
>
> The only way i can think of is to manually load the assembly containing that
> attributes (that I've discovered using cecil), then instantiate the
> attribute using the constructor-arguments information (from cecil), and then
> copy across all property-values (from cecil). Once you got the attribute
> instance, I can then execute the method. It seems to be a lot of work for
> such a _very_ common thing.

.net attributes have been designed to be instantiated at runtime.
Cecil is not a runtime feature, it just gives you an object model
which maps to the serialized metadata. Cecil has obviously no way to
instantiate an object based on this metadata.

If you want to instantiate attributes, you're looking at the wrong tool.

> Oh while I'm here, is there also an easy way to do
> type.IsAssignableFrom(type) on cecil? At the moment i'm recursively checking
> all the base-classes within its ancestry line, as well as their interfaces,
> but it feels very inefficient, considering it's also a very common thing
> (checking for types assignability is probably far more common than checking
> for an exact equality). Is there a better way to do this?

Not really, I don't think I have such a method around.

Jb

Hendry Luk

unread,
Apr 23, 2011, 10:52:28 PM4/23/11
to mono-...@googlegroups.com
Thanks for the response, Jb.
I was speculating there might be a way to convert (i.e. load) from cecil object models into the .net runtime.
I use cecil because the main business my application does is weaving assemblies (AOP), and unfortunately in few places I often need to read attribute metadata to control the weaving behavior.
I guess I will need to use both .net reflection and cecil for this, and somehow swap back and forth between them. Efficiency was my concern.

Thanks again

--
--
mono-cecil

Simon Cropp

unread,
Apr 24, 2011, 3:26:59 AM4/24/11
to mono-...@googlegroups.com
Hendry

Just to be clear Cecil can read attributes and you can even extract
out properties and constructor parameters.
The thing u can do with cecil is instantiate and instance of those
attributes at runtime. You would have to switch back to standard
reflection to do that.

So what does this mean for you... Just dont write code in your
attributes and you will be fine. Use Attributes soley for "metadata"
then have another class that does something with that metadata.

For example I have an attribute like this

public class NotifyPropertyAttribute : Attribute
{
public bool PerformEqualityCheck { get; set; }
public string[] AlsoNotifyFor { get; set; }
}

At weaving time I extract the PerformEqualityCheck property using this code

static bool? GetCheckForEquality(CustomAttribute notifyAttribute)
{
var performEqualityCheck =
notifyAttribute.Properties.FirstOrDefault(x => x.Name ==
"PerformEqualityCheck");
var equalityCheckValue = performEqualityCheck.Argument.Value;
if (equalityCheckValue != null)
{
return (bool)equalityCheckValue;
}
return null;
}

Would this approach meet your requirements?

> --
> --
> mono-cecil

Hendry Luk

unread,
Apr 24, 2011, 7:20:57 AM4/24/11
to mono-...@googlegroups.com
Yes, I'm able to get the metadata of the attributes. But i need to instantiate it because I do implement the behavior inside of the attribute for extensibility reason.
I guess mono-cecil is strictly behaving like .net assembly in the reflection-only mode (although the .net one is even more limited since you can't even inspect attribute at all, AFAIK).


The thing u can do with cecil is instantiate and instance of those attributes at runtime.

Did you mean "you can't"?

Cheers

--
--
mono-cecil

Simon Cropp

unread,
Apr 24, 2011, 7:32:42 AM4/24/11
to mono-...@googlegroups.com
sorry. your correction is correct :)

Why do u need to put code in the attribute?
Might be helpful if u post some code?

> --
> --
> mono-cecil

Hendry Luk

unread,
Apr 24, 2011, 8:59:33 AM4/24/11
to mono-...@googlegroups.com
My example is quite like what you described.
I have a set of attributes, in my case, of AOP advices.

You have different advice weaving behaviors depending on the attribute you put. E.g. there are AroundAttribute (intercept around the targets), BeforeAttribute, AfterAttribute, ExceptionAttribute, or even AnnotateAttribute (annotating the targets with additional attributes). I was reluctant to put an if-else logic to check these logics, because I want to have plugin-like capability in which third-party users are able to inherit from the attributes to provide their own custom behaviors.

As a workaround, I was thinking to have the child-classes to set a property which holds the type of the behavior-factory. However, I'm not sure if it works since it implies that the reflection would execute this "setter" coming from the child-attribute.

E.g.
public MyCustomAdviceAttribute: AdviceAttribute
{
      public MyCustomAdviceAttribute: base(typeof(MyAdviceBehaviorFactory))
      {
      }
}

And via cecil, I would get the value of AdviceAttribute.Attributes["Factory"]

I haven't tried that but I doubt that would work.

Another thing is, what's the best way to get a certain custom attributes allowing inheritance with cecil? There's only the property of CustomAttributes. Does it mean I have to interrogate each of their types, then traverse all the way up of each Attribute's line of inheritance, as well as all the way up each Method's line of inheritance and repeat and rinse?

Cheers

--
--
mono-cecil

Greg Young

unread,
Apr 24, 2011, 9:06:30 AM4/24/11
to mono-...@googlegroups.com

If you search this list for attribute i put up some code a while ago for handling attribute inheritance. If you cant find it i can next time i am at a computer. Think method name was geteffectiveattributes

> --
> --
> mono-cecil

Hendry Luk

unread,
Apr 24, 2011, 12:02:04 PM4/24/11
to mono-...@googlegroups.com
Thanks greg, I'll search around for that.

--
--
mono-cecil

Reply all
Reply to author
Forward
0 new messages