C# 调用具有属性的函数
我有一个函数,它使用stopwatch的一个实例通过启动和停止来测量方法的时间。 我是否可以在属性中定义该函数,并用该属性修饰任何给定的方法来度量该方法的时间? 这将降低LOC。 我不想使用任何第三方库C# 调用具有属性的函数,c#,methods,attributes,C#,Methods,Attributes,我有一个函数,它使用stopwatch的一个实例通过启动和停止来测量方法的时间。 我是否可以在属性中定义该函数,并用该属性修饰任何给定的方法来度量该方法的时间? 这将降低LOC。 我不想使用任何第三方库 public class AppTrace:BaseModel<AppTrace> { [DataMember] public string Comment; [DataMember] public string MethodName;
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);
}
}
公共类AppTrace:BaseModel
{
[数据成员]
公共字符串评论;
[数据成员]
公共字符串方法名;
[数据成员]
公共日期时间StartTimeStamp;
[数据成员]
公共时间;
[数据成员]
公共int-UserObjectId;
[数据成员]
公共字符串MachineName;
[数据成员]
公共int工具ID;
专用系统.Diagnostics.Stopwatch stpWatch;
公共AppTrace(字符串注释、字符串方法名、int userObjectId、字符串machineName=“”、int?toolId=null)
{
MethodName=MethodName;
UserObjectId=UserObjectId;
StartTimeStamp=DateTime.UtcNow;
评论=评论;
MachineName=MachineName;
stpWatch=new System.Diagnostics.Stopwatch();
stpWatch.Start();
}
公共AppTrace()
{
}
public void CloseTrace()
{
这个.stpWatch.Stop();
持续时间=Convert.ToInt32(this.stpWatch.elapsedmillisons);
}
}
如果不是属性,我可以在代表的帮助下完成这项工作吗?正如我在评论中所说的,通常不可能。您可以使用一些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;
}
}
然后您将能够测量方法调用时间。例如,classFoo
将用作测量目标
// 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
,该类将包含返回值和操作持续时间
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);
}
}
顺便说一下,
F#REPL
有#time
指令来测量调用时间。您可以从F.
调用任何.NET
代码。它集成到VisualStudio中,或者可以从命令行(fsi.exe
)调用。我不知道你的实际目标,所以它可能是合适的。正如我在评论中所说的,这通常是不可能的。您可以使用一些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;
}
}
然后您将能够测量方法调用时间。例如,classFoo
将用作测量目标
// 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
,该类将包含返回值和操作持续时间
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);
}
}
顺便说一下,
F#REPL
有#time
指令来测量调用时间。您可以从F.
调用任何.NET
代码。它集成到VisualStudio中,或者可以从命令行(fsi.exe
)调用。我不知道你的实际目标,所以它可能是合适的。看看,我认为它回答了你的问题。不,这是不可能的。您必须编写一些方法调用器实用程序,它将实际启动和停止StopWatch
(例如Invoke.Measure(()=>{/*dosomething*/})
)或使用一些AOP框架(例如,它在编译时使用IL重写).我在预定义的函数中启动和停止秒表。我有一个启动秒表的函数和一个停止秒表的函数。现在,为了测量任何给定方法的时间,我必须在之前和之后调用这两个函数。所以,为了减少loc,我可以使用属性吗?属性只能包含元信息,它不能执行任何操作。即使您将定义这样一个属性,一些上层代码也必须通过反射找到它,并以适当的方式使用它。使用静态实用程序和lambdas更简单。看看,我认为它回答了你的问题。不,这是不可能的。您必须编写一些方法调用器实用程序,它将实际启动和停止StopWatch
(例如Invoke.Measure(()=>{/*dosomething*/})
)或使用一些AOP框架(例如,它在编译时使用IL重写).我在预定义的函数中启动和停止秒表。我有一个启动秒表的函数和一个停止秒表的函数。现在,为了测量任何给定方法的时间,我必须在之前和之后调用这两个函数。所以,为了减少loc,我可以使用属性吗?属性只能包含元信息,它不能执行任何操作。即使您将定义这样一个属性,一些上层代码也必须通过反射找到它,并以适当的方式使用它。使用静态实用程序和lambdas更简单。我不能将方法名传递给属性属性,并在该属性中编写启动和停止的函数吗。让我添加这些函数。我可以使用委托来减少LOC吗?当然,您可以在属性中编写一个方法,它将使用秒表测量函数计时。但该函数不会自动调用。因此,您仍然需要编写一些代码来调用属性方法。我想这不值得麻烦。您可以将委托用于“逻辑”代码和静态助手,它们实际上将为您完成所有时间度量的脏活。这就是我在回答中写的东西。这里没有要添加的内容。我不能将方法名传递给属性属性,并在该属性中编写启动和停止的函数吗。让我添加这些函数。我可以使用委托来减少LOC吗?当然,您可以在属性中编写一个方法,它将使用秒表测量函数计时。但该函数不会自动调用。所以