【问题标题】:How to use CallerMemberName with an interface method如何通过接口方法使用 CallerMemberName
【发布时间】:2020-08-21 14:52:42
【问题描述】:

我正在浏览大约 700K 行代码。大量的接口实现和DI使用。我试图找出从哪里调用特定方法,因此我尝试使用[CallerMemberName]

我在谷歌等上看到的所有例子都是这样的:

public void TraceMessage(string message,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)

使用可选参数获取信息的地方。我的问题是这个方法是接口实现的一部分。因此,当我更改方法签名时,编译器会对我大喊大叫。

任何关于如何使接口方法与[CallerMembername] 配合使用的建议将不胜感激。

【问题讨论】:

  • 您可能需要更改接口以及随之而来的任何实现,但很难说出您的意思。这将有助于澄清您实际尝试进行的更改。
  • @Mike Zboray 感谢您的提问。我尝试像上面的示例一样添加可选参数。我希望因为这些参数是可选的,编译器不会关心。更改界面很棘手,因为这意味着要更改大量代码。
  • 所以你有一些像 ILogger.TraceMessage(string) 这样的接口方法,你想知道是谁在调用它?假设它在 Logger 中实现,您更改了 Logger.TraceMessage 以添加选项?
  • 不清楚你在问什么。在实现某个接口的成员的方法上,既不向参数添加默认值,也不向参数添加[CallerMemberName] 属性,都不会导致编译时错误。写类似 "...编译器对我大喊大叫" 之类的东西并不是一个有用的问题描述。它既不精确也不准确。如果您遇到问题,请发布一个好的minimal reproducible example,清楚地显示您尝试过的内容,确切解释该代码会发生什么,包括任何错误的确切文本消息,以及具体您无法弄清楚的内容。

标签: c# .net


【解决方案1】:

有一个类似的问题 - 发现我可以将 CallerMemberName 添加到接口方法中,如下所示。它确实会更改实现类的签名,但不会更改调用代码 - 如果这有意义的话!

如果这是接口中方法的当前签名

void TraceMessage(string message);

如下改变

void TraceMessage(string message,
    [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
    [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
    [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);

更新实现接口的类中的方法

public void TraceMessage(string message,
    [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
    [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
    [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
    {
        //  Log the params
    }

这仍然可以使用原始签名仅使用'message'参数调用,其他参数仍将被拾取,因此无需重构所有调用代码

TraceMessage("Testing");

(为简洁起见添加)

using System.Runtime.CompilerServices;

【讨论】:

  • 太棒了(竖起大拇指)
【解决方案2】:

您可以在不更改任何签名的情况下以不同的方式获取来电者姓名,请尝试this solution

using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();

// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);

此解决方案比您尝试使用的编译时慢得多,但侵入性要小得多。

如果性能很关键,并且您将 DI 与 IoC 容器一起使用,那么您可以检查它是否支持方面,例如 Unity.InterceptionNinject.Extensions.Interception。您需要实现一个方面(拦截器)并将其注册到容器中,here 是一个带有缓存拦截器的示例。

如果你不使用 IoC,你仍然可以使用 AOP 方法,并在你感兴趣的方法中添加某个方面。PostSharp 可以这样做,但它不是免费工具,here 是一些替代品。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多