2014-01-20 113 views
8
private void Method1() 
{ 
    //Do something 
    Log("Something","Method1"); 
} 

private void Method2() 
{ 
    //Do something 
    Log("Something","Method2"); 
} 

private void Log(string message, string method) 
{ 
    //Write to a log file 
    Trace.TraceInformation(message + "happened at " + method); 
} 

我有几个方法像上面的Method1和Method2,我想通过方法的名称作为参数,而不需要手动编辑代码的方式。传递方法的名称作为参数

这可能吗?

+3

有一个称为['CallerMemberNameAttribute'](http://msdn.microsoft.com/zh-cn/library/system.runtime.compilerservices.callermembername属性)的新属性(我认为在4.5中,需要最新的编译器) (v = vs.110).aspx)完成这个,但是在编译时使用字符串文字。或者,您可以使用linq表达式并查询表达式本身的名称,这通常是为'INotifyPropertyChanged'等属性完成的。 –

+1

而不是传递方法名称,您可以使用反射 –

+1

请参阅http://stackoverflow.com/questions/2652460/c-sharp-how-to-get-the-name-of-the-current-method-from-代码 –

回答

4

Jon Skeet的优秀答案。

但是,如果您不使用.NET 4.5,您可以尝试reflection。你应该怎么知道reflection must be used only when it is absolutely necessary. Do not over-use it for the sake of using it

走回来的 你可以做这样的事情,

using System.Reflection; //include Reflection namespace 

Console.WriteLine(MethodBase.GetCurrentMethod().Name) //Get the method-name of the current method 

在你的情况下,它会像下面,

private void Method1() 
{ 
    //Do something 
    Log("Something", System.Reflection.MethodBase.GetCurrentMethod().Name); 
} 

private void Method2() 
{ 
    //Do something 
    Log("Something", System.Reflection.MethodBase.GetCurrentMethod().Name); 
} 

private void Log(string message, string method) 
{ 
    //Write to a log file 
    Trace.TraceInformation(message + "happened at " + method); 
} 

编辑:

按以下来自@Jon Skeet的评论,如果你想.Net 4.5一种花哨和整洁的实施,检查出 NUGET包。

+0

我不能使用.NET 4.5或5,所以反射似乎只能这样做。 – gorkem

+0

有什么意义?您可以简单地将参数中的方法名称,因为您实际上知道它的名称,当您编写代码时。这不是解决问题的办法,只是帮助复制代码更简单。 –

+0

@ArtyomNeustroev:因为OP不能使用'.NET 4或.NET 4.5',所以我认为他留下了上述选择。如果'方法名称'将来会改变,或者如果有更多的方法呢?虽然这可以帮助复制粘贴代码更容易,但没有其他优雅的解决方案(如果您不使用.NET 4或.Net 4.5) –

15

由于C#5,这是一个使用caller info attributes非常简单:

private void Method1() 
{ 
    //Do something 
    Log("Something"); 
} 

private void Method2() 
{ 
    //Do something 
    Log("Something"); 
} 

private void Log(string message, [CallerMemberName] string method = null) 
{ 
    //Write to a log file 
    Trace.TraceInformation(message + "happened at " + method); 
} 

在得到这个工作方面:

  • 必须可以使用C#5(或更高版本)编译器,否则它将不知道专门处理属性。
  • 属性必须存在于目标环境中。选项有:
    • 在.NET 4.5的属性只是目前
    • 对于.NET 4,你可以使用Microsoft.Bcl NuGet package
    • 对于早期版本的.NET,复制attribute declaration到你自己的代码,并确保您使用相同的命名空间。当您稍后转到.NET的新版本时,您需要再次将其删除。
+0

优秀的答案乔恩。只是好奇:在'单元测试'的情况下,这个属性的表现如何?我们可以模拟吗? –

+1

@nowhewhomustnotbenamed .:这是一个编译时的事情 - 编译器注意到该参数已用该属性修饰并且具有默认值null,并且调用方未提供参数,因此它使用成员名称代替。我不确定你说的是什么样的嘲弄,但你可以很容易地明确地传递一个参数(例如'Log(“message”,“NotARealMethod”)) –

+0

感谢Jon。 '可选参数'。说得通。 :) –

0

面向方面编程(AOP)通常可以实现这样的任务。你可以看看PostSharp的免费版本,特别是Logging aspect对你有帮助。然后

你的代码如下所示:

[LogAspect("Something")] 
void Method1(string name) 
{ 

} 

您可以使用PostSharp到.NET框架2.0。