【问题标题】:Passing a method's name as a parameter将方法的名称作为参数传递
【发布时间】:2014-02-09 10:06:06
【问题描述】:
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,我想通过某种方式将方法的名称作为参数传递,而无需手动编辑代码。

这可能吗?

【问题讨论】:

标签: c# methods parameter-passing


【解决方案1】:

从 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 时,您需要再次将其删除。

【讨论】:

  • 优秀的答案乔恩。只是好奇:在unit testing 的情况下,该属性的行为究竟如何?我们可以模拟一下吗?
  • @nowhewhomustnotbenamed.: 这是编译时的事情 - 编译器注意到参数已经用属性修饰并且默认值为 null,调用者没有提供参数,所以它改为使用成员名称。我不确定您在谈论哪种嘲笑,但您可以轻松地明确传递一个参数(例如Log("message", "NotARealMethod")
  • 谢谢乔恩。 Optional Parameters。说得通。 :)
  • +1 如果在旧版本的 .NET 中但仍使用 c# 5 编译器,是否值得添加有关自己创建属性的详细信息?
  • @JoeStead:我会添加一个简短的说明,但不是完整的详细信息。
【解决方案2】:

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 的以下cmets,如果您想要.Net 4.5 那种花哨而简洁的实现,请查看Micrsoft.Bcl NUGET 包。

【讨论】:

  • 我不能使用 .NET 4.5 或 5,所以反射似乎是唯一的办法。
  • 重点是什么?您可以简单地将方法名称放在参数中,因为您在编写代码时实际上知道它的名称。这不是问题的解决方案,只是有助于更轻松地复制粘贴代码。
  • @ArtyomNeustroev:既然 OP 不能使用.NET 4 or .NET 4.5,我认为他只能选择上述选项。如果method-name 将来发生变化或有更多方法怎么办?虽然这有助于更轻松地复制粘贴代码,但没有其他优雅的解决方案(如果您不使用 .NET 4 或 .Net 4.5)
  • @gorkem:不,这不是唯一的方法。如果你可以使用 C# 5 编译器,你可以在自己添加属性。
  • @nowhewhomustnotbenamed.: 是的,你可以。在 .NET 4 中,只需使用 Micrsoft.Bcl NuGet 包;对于旧版本,只需从 MSDN 复制属性声明,确保将其放在与真实的相同的命名空间中。
【解决方案3】:

面向方面的编程(AOP)通常允许完成这样的任务。您可以查看PostSharp 的免费版本,尤其是Logging aspect 对您的情况很有帮助。

您的代码如下所示:

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

}

您可以使用 PostSharp 到 .NET framework 2.0。

【讨论】:

    猜你喜欢
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多