【问题标题】:is it possible in C# to know who called a static property/accessor?在 C# 中是否有可能知道谁调用了静态属性/访问器?
【发布时间】:2013-04-03 22:26:08
【问题描述】:

我的代码:

public class CLASS_A {    

public static Dictionary<int, CLASS_A> List = new Dictionary<int, CLASS_A>;
public static PP_CLASS pp = null;

 public static CLASS_A ID
 {
  get
  {
   int key = get_threadID;
   if (List.ContainsKey(key))
     return List[key];
   else
     return null;
   }
   set
   {
    int key = get_threadID;
    List[key] = value;
    }
   }

  public virtual void init(lib, name)
  {
    ...
    if (name != "")
    {
      if (pp == null)
       PP = this;
    } 
    ...
  }
}  

因此,无论哪个线程调用 init,它的 id 都用于存储它(无论谁调用)。例如,我的列表如下所示:

45 = CLASS_A_object0
67 = CLASS_A_object1
...

但是现在当另一个线程调用 pp 上的方法时,比如CLASS_A.pp.setWelcome,这将为 pp 返回 null,并抛出 null 异常!因为当调用 set 时,线程 id 会不同,不会在列表中。

那么我是否有可能知道调用了哪个对象以便进行反向查找?或者可能有不同的解决方案?

为什么我想要这个: 最初我们连接到一台设备,所以没关系。现在有多个设备,每个设备都有自己的 ip/port。初始代码只有 public static PP_CLASS pp = null; 所以其他人只会使用类名调用 pp 上的方法,一切都很好。

以前的行为:该软件从文件中选择设备列表,由于 pp 是静态的,它只与第一个设备对话。我添加了pp==null 行,我在最初的帖子中忘记了该行。因此,当代码开始时,pp==null 将为 true 并分配第一个设备,但现在对于其他设备,pp==null 将为 false,因此我无法与其他设备交谈。

如果需要更多详细信息,请告诉我。

【问题讨论】:

  • 能否将属性更改为方法并为“调用者”添加参数?然后只需跟进编译器向您抛出的所有错误。
  • 如果一个线程调用init 而另一个线程尝试使用pp,您的问题并不清楚您想要发生什么。
  • 告诉我们更多关于您的用例的信息。为什么要以线程为键来存储对象?每个线程不会有一个单独的 PP 实例,在调用 PP 后,所有线程都会有一个共享的 PP。这没有多大意义,因为它代表 PP 和您的 ID 属性没有关系。我想知道您是否正在寻找 ThreadStatic:msdn.microsoft.com/en-us/library/…。另外 - 使用 List 作为标识符也不是一件好事。
  • 我一开始也想过,但是文件很多,不切实际。
  • 我还建议使用ThreadLocal&lt;T&gt; 类,因为它可以为调用它的每个线程处理对象的唯一实例的自动实例化,这就是您的代码似乎要做的事情。

标签: c# properties static accessor


【解决方案1】:

从C# 5.0(2012 年 8 月)开始,有一个新功能“Caller Info Attribute”。如果您的类存储在单独的文件中,您可以使用CallerFilePathAttribute 来注册实际调用的类。

来自MSDN的示例:

// using System.Runtime.CompilerServices 
// using System.Diagnostics; 

public void DoProcessing()
{
    TraceMessage("Something happened.");
}

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}

// Sample Output: 
//  message: Something happened. 
//  member name: DoProcessing 
//  source file path: c:\Users\username\Documents\Visual Studio 2012\Projects\CallerInfoCS\CallerInfoCS\Form1.cs 
//  source line number: 31

【讨论】:

  • 那个很有趣。 (过去一直使用stacktrace,这个看起来更简单)
【解决方案2】:

您可以尝试检查堆栈跟踪。

var trace = new System.Diagnostics.StackTrace();

或者只获取调用线路,它应该是这样的:

var caller = new System.Diagnostics.StackTrace().GetFrame(1)

【讨论】:

    猜你喜欢
    • 2018-11-08
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 2015-05-25
    • 2020-10-16
    • 1970-01-01
    相关资源
    最近更新 更多