I have some functions for which I want to log time consumed in them.
DBResult LongTask(DBCommand command)
{
...
}
Is there a way to attchieve this
[LogTimeUsed()]
DBResult LongTask(DBCommand command)
{
...
}
开发者_StackOverflowSo that I can have class/function somewhere which gets called every time when this function is called and I can inject my own code, get access to command and DBResult and log time spent in function?
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>()
)
);
You could use Castle DynamicProxy.
DynamicProxy generates proxies for your objects that you can use to transparently add or alter behavior to them, provide pre/post processing and many other things.
If you're not handling that particular type of attribute yourself, you should look into Aspect Orientated Programming, using something like PostSharp
You can do this using PostSharp
Also check the answer to my question on SO - Aspect Oriented Logging with Unity\T4\anything else
Just to add to the list of third party stuff out there is spring AOP (Spring is large and popular framework that has been ported to .net from Java)
http://www.springframework.net/doc-latest/reference/html/aop.html
The question is looking for a way to create a decorator in c# by using c# attributes, to attempt to create the decorator syntax as seen in python (which is excellent... C# community take note)
Something similar could be acheived by embedding the 'attribute' in your method name (e.g. LongTask_LogTimeUsed) then have a small amount of (boilerplate) code INSIDE the LongTask method that reads its method name delegating the pre or post processing off to appropriate handlers:
How to get the name of the current method from code
How to get passed in parameters over to the pre or post processors would need thinking about though.
精彩评论