C# 调用具有属性的函数

C# 调用具有属性的函数,c#,methods,attributes,C#,Methods,Attributes,我有一个函数,它使用stopwatch的一个实例通过启动和停止来测量方法的时间。 我是否可以在属性中定义该函数,并用该属性修饰任何给定的方法来度量该方法的时间? 这将降低LOC。 我不想使用任何第三方库 public class AppTrace:BaseModel<AppTrace> { [DataMember] public string Comment; [DataMember] public string MethodName;

我有一个函数,它使用stopwatch的一个实例通过启动和停止来测量方法的时间。 我是否可以在属性中定义该函数,并用该属性修饰任何给定的方法来度量该方法的时间? 这将降低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);
    }

}
公共类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;
    }  
}
然后您将能够测量方法调用时间。例如,class
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
,该类将包含返回值和操作持续时间

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;
    }  
}
然后您将能够测量方法调用时间。例如,class
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
,该类将包含返回值和操作持续时间

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吗?当然,您可以在属性中编写一个方法,它将使用秒表测量函数计时。但该函数不会自动调用。所以