0

I was wondering how to go about writing a custom attribute which can access both the input and output parameters of a function.

Below is an example of what I wish to achieve

[CustomAttribute("Creating Foo")]
public Foo CreateFoo(Foo newFoo)
{
    //do logic
    return newlyCreatedFoo;
}

From this, the CustomAttribute will create an entry in a DB with the "Creating Foo" tag, which is easy enough to do, but I want to be able to access both newFoo and newlyCreatedFoo as well. Is this possible?

Picrofo Software
  • 5,475
  • 3
  • 23
  • 37
Thewads
  • 4,953
  • 11
  • 55
  • 71

3 Answers3

4

Custom attributes can't do that in general: their purpose is to add metadata to a method to view during reflection.

That being said, there are some cases where attributes are leveraged to do that. For example, ASP.Net MVC uses custom attributes that implement IAuthorizationFilter to provide security for some web pages. This works because ASP is using reflection to launch the methods in the first place. Once it gets the method it checks to see if any attributes are IAuthorizationFilters, and does some extra work when they are. See this link for some more info.

Another way to think about this is to consider aspect-oriented programming. I think AOP frameworks for c# tend to make compile time decorations to methods based on attributes that implement a certain interface, but I have not used one.

My favorite way to deal with this is the good old Proxy pattern. Create a logging proxy.

tallseth
  • 3,635
  • 1
  • 23
  • 24
1

I am afraid that this is not possible with custom attributes.

This could be achieved with post compilation processing. Tools like PostSharp would allow you to achieve this functionality.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Why? This is nothing more than a comment. – casperOne Nov 30 '12 at 14:26
  • 1
    @casperOne, did you read the last line of the OP? I quote: `Is this possible?`. Now read my answer once again. The OP asks whether this is possible and the answer is *no*. – Darin Dimitrov Nov 30 '12 at 14:28
  • I was afraid this may be the answer. I don't suppose you would know of any alternatives to achieve something similar? – Thewads Nov 30 '12 at 14:30
  • 1
    I read it. But we can do better than this. An explanation of *why* would be a *much* better contribution to the site. Taking narrowly-constrained view on a question such as this and answering in the narrowest way possible without any further background for the benefit of easy reputation is not the impression that Stack Overflow wants to give. – casperOne Nov 30 '12 at 14:30
  • @Thewads, there might be some alternatives but you will have to provide more details about your scenario and why you need such functionality. – Darin Dimitrov Nov 30 '12 at 14:31
  • @casperOne, I didn't find it necessary to repeat myself in saying `because .NET custom attributes do not allow such functionality`. I thought this was more than evident from an my answer in which I said `no`. Anyway, I won't be nitpicking anymore. – Darin Dimitrov Nov 30 '12 at 14:33
  • It is essentially going to be used to keep an audit trail of activity. Whenever a user creates/edits something then an audit will be created. Just thought that method decoration would be a little nicer and generic than having to manually code it on every method – Thewads Nov 30 '12 at 14:33
  • @Thewads, I see. Tools like [`PostSharp`](http://www.sharpcrafters.com/postsharp/features) could help you in achieving this task. I have updated my answer to include this information. As an alternative, if the methods are virtual you could write a derived class which would intercept the calls, perform the auditing and call the base method. Depending on your exact scenario this might be more or less a good solution. – Darin Dimitrov Nov 30 '12 at 14:35
0

Perhaps you should rephrase your question to "How can I intercept calls to specific methods and log the arguments"?

A custom attribute is just a decoration on a method. It does not intercept or in any way affect the execution of a method. It doesn't even know what member it is attached to.

If you want to intercept the calls you can use a dependency injection framework, or any other AOP framework for .NET to do just that. Some of them actually use attributes to mark their targets, but that isn't a requirement.

PostSharp is just one AOP framework for .NET.

Another option, is to use an IoC/Dependency Injection library like MEF to wrap your class in a proxy object that will intercept all calls and only log the values of the methods decorated with a special attribute.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236