There is no built in way to do this in .NET.
If your wish is not to use any 3rd party libraries (as you said in one of your comments), doing code weaving or dynamic proxy generation is a lot of work. In that case it's better to step away from using attributes and go with the decorator design pattern. Here's an example:
// Define an interface for the operation
public interface IMyLongRunningTask
{
DBResult longTask(DBCommand command);
}
// Define an implementation for the operation:
public class MyLongRunningTask : IMyLongRunningTask
{
public DBResult longTask(DBCommand command)
{
// code here
}
}
And now you can write a decorator for the IMyLongRunningTask:
public class MyLongRunningTaskMonitor : IMyLongRunningTask
{
private readonly IMyLongRunningTask wrappedService;
private readonly ILogger logger;
public MyLongRunningTaskMonitor(IMyLongRunningTask wrapped,
ILogger logger)
{
this.wrappedService = wrapped;
this.logger = logger;
}
public DBResult longTask(DBCommand command)
{
var watch = Stopwatch.CreateNew();
var result = this.wrappedService.longTask(command);
this.logger.Log("longTask executed in " +
watch.ElapsedMilliseconds + " ms.");
return result;
}
}
When you use dependency injection, you can easily configure an MyLongRunningTaskMonitor
to be returned when an IMyLongRunningTask
is requested. For instance:
container.Register<IMyLongRunningTask>(() =>
new MyLongRunningTaskMonitor(
container.GetInstance<MyLongRunningTask>(),
container.GetInstance<ILogger>()
)
);