Ideally, I want to create a filter that inherits from ActionFilterAttribute that I can apply in Global.asax that will create performance counters for all the actions in my application. That problem is easy, but the issue is that I want the performance counters to have the method signature of the action that they are attached to in their name. However, I can't find a way to extract the method name of the method that an attribute is attached to during construction. This is causing me to have to apply the attributes to each action individually and pass in their signature as a parameter. However, this poses obvious problems (i.e. updates to method signature not automatically synchronized with perf counter naming).
To simplify the problem, if I attach an attribute to a method of any kind, can I access the name/signature of the method that it is attached to? I'm looking for a generic solution that works for attributes that don't derive from ActionFilterAttribute also.
public class SomeAttribute : ActionFilterAttribute
{
public string FunctionSignature { get; set; }
public SomeAttribute()
{
this.FunctionName = { HOW DO I GET THE NAME OF THE METHOD I'M ON WITHOUT PASSING IT IN AS AN INPUT ARGUMENT? }
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Some code to update perf counter(s) with recorded time that will use string.Format("{0}: Avg. Time or Something", this.FunctionSignature).
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Some code to record time.
}
}
[SomeAttribute]
public void SomeMethod()
{
// Some code.
}
The following code fragment specifies that a custom attribute can be applied to any class or method: C# Copy. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] End Class.
it lets you turn any public method of a WebService subclass into a method that you can expose as part of the Web Service merely by attaching the [WebMethod] attribute to the method definition.
Attributes are used to impose conditions or to increase the efficiency of a piece of code. There are built-in attributes present in C# but programmers may create their own attributes, such attributes are called Custom attributes. To create custom attributes we must construct classes that derive from the System.
Find the name of executing action:
var actionName = filterContext.ActionDescriptor.ActionName;
or alternatively
var actionName = filterContext.RouteData.Values["action"] as string
Find parameters (Name, Type, DefaultValue):
var parameters = filterContext.ActionDescriptor.GetParameters();
Find parameters values:
var value= filterContext.ActionParameters["parameterName"];
As I understand, you want generic solution for that, not related to ActionFilterAttribute or asp.net at all. Then you can use Aspect Oriented Programming, and best implementation of that for .NET is PostSharp. Free version of that library is enough to achieve your goal. For example:
class Program
{
static void Main(string[] args)
{
Test();
Console.ReadKey();
}
[Measure]
public static void Test() {
Thread.Sleep(1000);
}
}
[Serializable]
public sealed class MeasureAttribute : OnMethodBoundaryAspect
{
private string _methodName;
[NonSerialized]
private Stopwatch _watch;
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) {
base.CompileTimeInitialize(method, aspectInfo);
// save method name at _compile_ time
_methodName = method.Name;
}
public override void OnEntry(MethodExecutionArgs args) {
base.OnEntry(args);
// here you have access to everything about method
_watch = Stopwatch.StartNew();
}
public override void OnExit(MethodExecutionArgs args) {
base.OnExit(args);
if (_watch != null) {
_watch.Stop();
Console.WriteLine("Method {0} took {1}ms", _methodName, _watch.ElapsedMilliseconds);
}
}
public override void OnException(MethodExecutionArgs args) {
base.OnException(args);
// do what you want on exception
}
}
Here we create MeasureAttribute which you can apply on any method and intercept method invocation in many points. Even more, you can even apply it dynamically to all methods based on some condition (i.e. all methods in given class or whole assembly, or whatever). It also allows you to save some information in compile time, to increase perfomance. In example above we save method name once during compilation.
PostSharp (and AOP in general) can do much more than that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With