如何自动识别对某个功能的特定调用?
这个例子是简化的,我有(某种程度上)更好的理由想要这个,而不是从例子中看出来。
如果我的代码如下:
...
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
中):
答案 0 :(得分:2)
使用.NET 4.5,您可以使用某些编译器“帮助程序”(例如调用行#等)来声明参数。
void method1(useful params,
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0)
{ ... }
然后你会调用允许编译器提供默认参数:
myObj.method1(parameters);
在函数内部,其他参数将填充有用的信息。
有关详细信息,请参阅[CallerFilePath]
属性帮助:http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callerfilepathattribute.aspx
答案 1 :(得分:1)
.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));
}
}
http://intellitect.com/new-attributes-for-tracelogging-information-in-net-4-5/
答案 2 :(得分:1)
String callerName = (new StackTrace()).GetFrame(0).GetMethod().Name;
Int lineNo = (new StackTrace()).GetFrame(0).GetFileLineNumber();