我有一个函数,它使用秒表的实例通过启动和停止来测量方法的时间。我是否可以在属性中定义该函数,并使用该属性修饰任何给定的方法,以测量该方法的时间?这将降低LOC。我不想使用任何第三方库。
public class AppTrace:BaseModel<AppTrace>
{
[DataMember]
public string Comment;
[DataMember]
public string MethodName;
[DataMember]
public DateTime StartTimeStamp;
[DataMember]
public int Duration;
[DataMember]
public int UserObjectId;
[DataMember]
public string MachineName;
[DataMember]
public int ToolId;
private System.Diagnostics.Stopwatch stpWatch;
public AppTrace(string comment,string methodName,int userObjectId ,string machineName = "",int? toolId=null)
{
MethodName = methodName;
UserObjectId = userObjectId;
StartTimeStamp = DateTime.UtcNow;
Comment = comment;
MachineName = machineName;
stpWatch = new System.Diagnostics.Stopwatch();
stpWatch.Start();
}
public AppTrace()
{
}
public void CloseTrace()
{
this.stpWatch.Stop();
Duration=Convert.ToInt32( this.stpWatch.ElapsedMilliseconds);
}
}如果不是属性,我可以在委托的帮助下做到这一点吗?
发布于 2015-07-10 19:16:51
正如我在评论中所说,这通常是不可能的。您可以使用一些AOP框架,它可以相当成功地处理这类事情。或者编写一些调用实用程序。
在最简单的情况下,您的实用程序可能如下所示:
public static class Invoke
{
public static TimeSpan Measure(Action action)
{
if (action == null)
{
throw new ArgumentNullException();
}
var stopWatch = Stopwatch.StartNew();
action();
stopWatch.Stop();
return stopWatch.Elapsed;
}
}然后,您将能够测量方法调用时间。例如,类Foo将用作测量目标。
// don't use such naming in production code
public class Foo
{
public void DoWork1()
{
// imitating hard computations
Thread.Sleep(TimeSpan.FromSeconds(5));
}
public void DoWork2(int param1)
{
// imitating hard computations
Thread.Sleep(param1);
}
}
public static class Program
{
public static void Main()
{
var foo = new Foo();
// signature of foo.DoWork1 is suitable for Invoke.Measure,
//so you can use it as MethodGroup
var time1 = Invoke.Measure(foo.DoWork1);
Console.WriteLine("Time for 'DoWork1' is {0}s", time1.TotalSeconds);
// signature of foo.DoWork2 is not suitable for Invoke.Measure,
// so you have to call it inside additional lambda
var time2 = Invoke.Measure(() => foo.DoWork2(42));
Console.WriteLine("Time for 'DoWork2' is {0}s", time2.TotalSeconds);
}
}对于返回一些值的方法来说,这会比较困难,但也可以实现。添加助手类Timed<T>,它将包含返回值和操作持续时间。
public class Timed<T>
{
public readonly TimeSpan Duration;
public readonly T Result;
// making constructor private to force static factories usage
private Timed(T result, TimeSpan duration)
{
Result = result;
Duration = duration;
}
// static factory method instead of constructor, for generic parameter
// type inference
public static Timed<T> Create(T result, TimeSpan duration)
{
return new Timed<T>(result, duration);
}
}那么将需要Invoke.Measure的重载。
public static class Invoke
{
// Func<T> instead of Action
public static Timed<T> Measure(Func<T> func)
{
if (func== null)
{
throw new ArgumentNullException();
}
var stopWatch = Stopwatch.StartNew();
var result = func();
stopWatch.Stop();
return Timed.Create(result, stopWatch.Elapsed);
}
}顺便说一句,F# REPL有#time指令来测量调用时间。您可以从F#调用任何.NET代码。它被集成到Visual Studio中,或者可以从命令行(fsi.exe)调用。我不知道你的实际目标,所以它可能是合适的。
https://stackoverflow.com/questions/31337614
复制相似问题