C# 如何自动识别对函数的特定调用?

C# 如何自动识别对函数的特定调用?,c#,.net,reflection,C#,.net,Reflection,如何自动识别对函数的特定调用 这个例子被简化了,我有(某种程度上)比这个例子中看起来更好的理由 如果我有这样的代码: ... myObj.method1("locationA", otherParams); ... myObj.method1("locationB", unrelatedParams); ... 我想知道如何自动生成标识符来代替“locationA”和“locationB”,这样我就可以知道哪行代码正在进行调用 它不是为每个位置硬编码标识符的选项,例如,它不能是递增的数字。它必

如何自动识别对函数的特定调用

这个例子被简化了,我有(某种程度上)比这个例子中看起来更好的理由

如果我有这样的代码:

...
myObj.method1("locationA", otherParams);
...
myObj.method1("locationB", unrelatedParams);
...
我想知道如何自动生成标识符来代替“locationA”和“locationB”,这样我就可以知道哪行代码正在进行调用

它不是为每个位置硬编码标识符的选项,例如,它不能是递增的数字。它必须是每次为相同的函数调用生成的相同标识符

我的想法是,我们可能能够使用反射(虽然我不知道是否有类似IL行号的东西可用),但我愿意接受关于如何做到这一点的任何其他想法,只要它满足上述条件

谢谢你的帮助


更多信息: 询问者是我的同事,提供的答案似乎解决了问题,但如果有更好的选择,我会提供一些额外的信息。我们想要标识特定位置的原因是,我们正在服务器端代码(c#)和客户端代码(JavaScript)之间进行提示(将消息发送回用户进行交互)。如果我们有一系列基于应用程序状态的提示,比如说,第一个提示发生在数据库中某个东西被锁定并询问用户要做什么(例如,取消)时,第二个提示发生在之后。在移动到第二个提示符之前,我们需要处理第一个提示符,因此我们退出服务器代码并返回第一个提示符

当我们对提示进行编码时,我们会动态地为其分配一个ID(在这种情况下,当前会自动增加一个ID,以避免硬编码(即1、2、3或GUID等)。每次调用有问题的方法时,都会重置此动态标识(以便ID一致;第一个提示的ID为“1”,第二个为“2”)

其思想是,当用户回答并重试时,我们将答案分配给一个列表,并调用操作,然后将列表中的提示答案与代码中的特定提示匹配。然后我们转到下一个提示,然后重复相同的过程

但是,如果当我们返回到带有两个提示的方法时,锁不再存在(第一个提示),我们不会分支到代码的该部分(在提示之前会检查锁)因此,我们跳转到第二个提示,但第二个提示将自动生成ID 1,而不是2,并认为它已经有了答案,但它没有

我突出显示了创建ID的代码,并查看是否有与提示ID匹配的答案(答案列表存储在
PromptHandler
中):


.NET 4.5具有一些跟踪属性,可以满足您的需要

using System.Runtime.CompilerServices;

void Main()
{
    var myObj = new MyClass();
    myObj.Method1("foo", 1);
}

public class MyClass
{
    public void Method1(object someArgument, object someOtherArgument,
                 [CallerMemberName] string callerMemberName = null,
                 [CallerFilePath] string callerFilePath = null,
                 [CallerLineNumber] int callerLineNumber = 0)
    {
        Console.WriteLine(
             string.Format("Called with {0}, {1} from method {2} in file {3} at line number {4}",
                someArgument, someOtherArgument, 
                callerMemberName, callerFilePath, callerLineNumber));
    }
}

.NET 4.5具有一些跟踪属性,可以满足您的需要

using System.Runtime.CompilerServices;

void Main()
{
    var myObj = new MyClass();
    myObj.Method1("foo", 1);
}

public class MyClass
{
    public void Method1(object someArgument, object someOtherArgument,
                 [CallerMemberName] string callerMemberName = null,
                 [CallerFilePath] string callerFilePath = null,
                 [CallerLineNumber] int callerLineNumber = 0)
    {
        Console.WriteLine(
             string.Format("Called with {0}, {1} from method {2} in file {3} at line number {4}",
                someArgument, someOtherArgument, 
                callerMemberName, callerFilePath, callerLineNumber));
    }
}

使用.NET 4.5,您可以使用某些编译器“助手”(如调用行#等)对参数进行属性化

然后调用允许编译器提供默认参数:

myObj.method1(parameters);
在函数内部,这些其他参数将填充有用的信息


有关详细信息,请参阅
[CallerFilePath]
属性帮助:

使用.NET 4.5,您可以使用某些编译器“帮助程序”(如调用行)对参数进行属性设置

然后调用允许编译器提供默认参数:

myObj.method1(parameters);
在函数内部,这些其他参数将填充有用的信息


有关更多信息,请参阅
[CallerFilePath]
属性帮助:

请注意,除了用于调试/日志记录之外,这几乎肯定是个坏主意。如果您使用此信息来更改程序的运行方式,则有更好的方法(关于什么,没有更多信息很难说)因此,除非您确定这是您想要的,否则在走这条路之前一定要非常小心。谢谢Servy,我们知道这一点。虽然我们不使用它进行调试或记录,但我们也不使用它进行程序控制。它必须能够识别集合中的哪个对象是在特定行创建的,而无需为特定行硬编码一些id。感谢您的警告,但我们相信我们理解为什么这通常是不好的。请注意,除了用于调试/记录之外,这几乎肯定是一个坏主意。如果您使用此信息来更改程序的运行方式,那么有更好的方法(至于什么,没有更多信息很难说)因此,除非您确定这是您想要的,否则在走这条路之前一定要非常小心。谢谢Servy,我们知道这一点。虽然我们不使用它进行调试或记录,但我们也不使用它进行程序控制。它必须能够识别集合中的哪个对象是在特定行创建的,而无需为该行硬编码一些id。感谢您的警告,但我们相信我们理解为什么这通常是不好的。谢谢,这是一个清晰的解释,应该适用于我们的情况。谢谢,这是一个清晰的解释,应该适用于我们的情况。