tags:

views:

72

answers:

2

I am working on a Asp.net MVC project and I am wondering if there is a way for the attributes to talk to other attributes.

For example, I have the following attributes

public class SuperLoggerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //Do something super
    }
}

public class NormalLoggerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //Do something normal ONLY if the super attribute isn't applied 
    }
}

And I have the following controllers

[NormalLogger]
public class NormalBaseController : Controller
{

}

public class PersonController: NormalBaseController
{

}

[SuperLogger]
public class SuperController: NormalBaseControler
{

}

So basically, I want my SuperController to use SuperLogger and ignore NormalLogger (which was applied in the base), and PersonController should use the NormalLogger since it's not "overrided" by the SuperLogger. Is there a way to do that?

Thanks,

Chi

+1  A: 

Why not just have SuperLoggerAttribute inherit from NormalLoggerAttribute and override the Log method?

arootbeer
-1: By doing this, SuperController would have both the NormalLoggerAttribute and the SuperLoggerAttribute applied, which is not what Chi Chan intended to do.
Tom Vervoort
Does SuperController not already have both, by virtue of extending an attributed base class?
arootbeer
Thank you arootbeer. But by doing so I will have to Add [NormalLogger] on PersonController. I want to avoid doing that because I have a lot of controllers that inherit from the base and I only have one "Super" controller that I want a different behavior with.
Chi Chan
Why would you have to add NormalLogger on PersonController? It would still inherit the NormalLogger attribute from NormalController as it's doing now.
arootbeer
I have just tried this. If you keep [NormalLogger] on BaseController, SuperController will execute NormalLogger (defined in BaseController), and then it will execute SuperLogger (defined in SuperController). I can inherit SuperLogger from NormalLogger to save code, but it won't stop it from executing NormalLogger.
Chi Chan
Okay. It sounds like the runtime is calling OnActionExecuted explicitly on both attributes, then. At this point it appears we diverge into synchronization code, which I'd think is a Really Bad Idea because the NormalLogger is not going to be the same instance as the SuperLogger. Looks like you're off to flow control similar to Tom's suggestion.
arootbeer
Actually, I am not sure how flow control can help out with this. If I apply [Logger(LoggerType.Normal)] on BaseController and [Logger(LoggerType.Super)] on SuperController. It will still call [Logger(LoggerType.Normal)] on SuperController because SuperController is inherited from BaseController. I am currently using a "God object" to hack away with this. But we all know it's a bad idea to play God. ;)
Chi Chan
"If you do it right, no one will be sure you've done anything at all."
arootbeer
Now that that's out of the way - The only way I can see is to check whether the class to which the attribute is applied is SuperController, and if it is then don't run the code in NormalLogger. I have very little experience with attributing, so I can't even tell you for sure that you can check the class to which an attribute is applied.
arootbeer
A: 

I think this should work:

public enum LoggerTypes
{
    Normal,
    Super
}

public class LoggerAttribute : ActionFilterAttribute
{
    public LoggerAttribute() : base()
    {
        LoggerType = LoggerTypes.Normal;
    }

    public LoggerAttribute(LoggerTypes loggerType) : base()
    {
        LoggerType = loggerType;
    }

    public LoggerTypes LoggerType
    {
        get; 
        set;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (LoggerType == LoggerTypes.Super)
        {
            //
        }
        else
        {
            //
        }
    }

Usage:

[Logger(LoggerTypes.Normal)]

or

[Logger(LoggerTypes.Super)]
Tom Vervoort