2009-03-05 41 views
46

thể trùng lặp:
How can I find the method that called the current method?Lấy tên phương pháp gọi điện thoại từ bên trong một phương pháp

Tôi có một phương pháp trong một đối tượng mà được gọi từ một số nơi trong phạm vi đối tượng. Có một cách nhanh chóng và dễ dàng để có được tên của phương pháp được gọi là phương pháp phổ biến này.

Pseudo mã ví dụ:

public Main() 
{ 
    PopularMethod(); 
} 

public ButtonClick(object sender, EventArgs e) 
{ 
    PopularMethod(); 
} 

public Button2Click(object sender, EventArgs e) 
{ 
    PopularMethod(); 
} 

public void PopularMethod() 
{ 
    //Get calling method name 
} 

Trong PopularMethod() Tôi muốn nhìn thấy giá trị của Main nếu nó được gọi là từ Main ... Tôi muốn xem "ButtonClick" nếu PopularMethod() được gọi từ ButtonClick

Tôi đã xem System.Reflection.MethodBase.GetCurrentMethod() nhưng điều đó sẽ không giúp tôi có được phương pháp gọi điện. Tôi đã nhìn vào lớp StackTrace nhưng tôi thực sự không thưởng thức chạy toàn bộ dấu vết ngăn xếp mỗi khi phương thức đó được gọi.

Trả lời

67

Tôi không nghĩ rằng nó có thể được thực hiện mà không truy tìm chồng. Tuy nhiên, nó khá đơn giản để làm điều đó:

StackTrace stackTrace = new StackTrace(); 
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod(); 
Console.WriteLine(methodBase.Name); // e.g. 

Tuy nhiên, tôi nghĩ bạn thực sự phải dừng lại và tự hỏi nếu điều này là cần thiết.

+0

Để biết thêm thông tin, hãy xem: http://discuss.joelonsoftware.com/default.asp?dotnet.12.511358.10 –

+3

System.Diagnostics là không gian tên của StackTrace, System.Reflection là vùng tên của MethodBase. – Guvante

+0

Jason - Cảm ơn bạn, tôi không chắc tài nguyên chuyên sâu về phương pháp "StackTrace" như thế nào, nhưng điều này làm tôi có được những gì tôi đang tìm kiếm. Đây chỉ là một khối mã gỡ lỗi cho tôi, điều này sẽ không đi vào sản xuất. Cảm ơn lần nữa vì sự giúp đỡ của bạn ! –

16

Điều này thực sự rất đơn giản.

public void PopularMethod() 
{ 
    var currentMethod = System.Reflection.MethodInfo 
     .GetCurrentMethod(); // as MethodBase 
} 

Nhưng hãy thận trọng, nếu nội tuyến phương pháp này có hiệu lực. Bạn có thể làm điều này để đảm bảo rằng trình biên dịch JIT sẽ không bị cản trở.

[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
public void PopularMethod() 
{ 
    var currentMethod = System.Reflection.MethodInfo 
     .GetCurrentMethod(); 
} 

Để có được phương pháp gọi:

[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
public void PopularMethod() 
{ 
    // 1 == skip frames, false = no file info 
    var callingMethod = new System.Diagnostics.StackTrace(1, false) 
     .GetFrame(0).GetMethod(); 
} 
+3

John Leidgren - Điều đó sẽ cho tôi tên "PopularMethod", nhưng tôi muốn tên của phương thức được gọi là PopularMethod. –

+1

Phải, dấu vết ngăn xếp là những gì bạn cần sau đó. Tôi đã hiểu sai câu hỏi của bạn. –

+0

Chỉ sử dụng .GetFrame (1) thay vào đó, phải không? –

5

Chỉ cần vượt qua trong một tham số

public void PopularMethod(object sender) 
{ 

} 

IMO: Nếu đó là đủ tốt cho các sự kiện nó phải đủ tốt cho việc này.

+0

Sruly - Có đó chắc chắn là một lựa chọn, tôi đã cố gắng để làm điều đó mà không thay đổi cuộc gọi phương thức. Đây sẽ là lựa chọn cuối cùng của tôi. –

+0

Trừ khi bạn phơi bày điều này dưới dạng API công khai, tại sao bạn lại phải trải qua một sự phức tạp và sử dụng sự phản chiếu nếu bạn có thể thực hiện theo cách này? REMember KISS – Sruly

+0

Đây là câu trả lời TỐT NHẤT, không sử dụng sự phản chiếu hoặc các nội dung khác, ID người gọi qua một tham số. –

0

Tôi nghĩ bạn cần sử dụng lớp StackTrace và sau đó StackFrame.GetMethod() trên khung tiếp theo.

Điều này có vẻ giống như một điều lạ khi sử dụng Reflection. Nếu bạn đang xác định PopularMethod, không thể đi xác định tham số hoặc thứ gì đó để chuyển thông tin bạn thực sự muốn. (Hoặc đặt vào một lớp cơ sở hoặc một cái gì đó ...)

1

Trong khi bạn có thể definitley nhất theo dõi ngăn xếp và con số nó ra theo cách đó, tôi sẽ thúc giục bạn suy nghĩ lại thiết kế của bạn. Nếu phương pháp của bạn cần phải biết về một số loại "nhà nước", tôi sẽ nói chỉ cần tạo một enum hoặc một cái gì đó, và lấy đó như là một tham số để PopularMethod của bạn(). Một cái gì đó dọc theo những dòng đó. Dựa trên những gì bạn đang đăng, truy tìm ngăn xếp sẽ quá mức IMO.

4

Tôi thường thấy mình muốn làm điều này, nhưng luôn luôn kết thúc việc tái cấu trúc thiết kế của hệ thống của mình nên tôi không nhận được mẫu "Chống vẫy chó" này. Kết quả luôn là một kiến ​​trúc mạnh mẽ hơn.

+0

Đây có phải là câu trả lời không? –

104

Trong NET 4.5/C# 5, điều này rất đơn giản:

public void PopularMethod([CallerMemberName] string caller = null) 
{ 
    // look at caller 
} 

Các biên dịch thêm tên của người gọi tự động; như vậy:

void Foo() { 
    PopularMethod(); 
} 

sẽ chuyển vào "Foo".

+0

giải pháp tuyệt vời !! không thể chờ đợi cho đến khi chúng tôi chuyển đổi sang 4.5 ở đây (nó sẽ là một lúc) nhưng tôi chắc chắn sẽ ghi nhớ điều này! cảm ơn bạn! –

+1

Hậu quả của giải pháp này là gì? – Feckmore

+3

@ Không còn gì nữa: trình biên dịch thêm nó dưới dạng chữ trong quá trình biên dịch. Nó sẽ nhanh hơn bất cứ thứ gì như nhìn vào StackTrace, v.v.về cơ bản nó được biên dịch như PopularMethod ("CurrentMethodName") –

Các vấn đề liên quan