2010-04-16 28 views
265

Tôi biết bạn có thể làmLàm thế nào để có được tên của phương pháp hiện tại từ mã

this.GetType().FullName 

Để có được

My.Current.Class 

Nhưng những gì tôi có thể gọi để có được

My.Current.Class.CurrentMethod 
+9

'this.ToString()' cung cấp cho bạn tên lớp hiện tại chỉ khi bạn không thực hiện bất kỳ điều gì đặc biệt trong chuỗi 'công khai ghi đè lên ToString()' của riêng bạn. 'GetType(). FullName' không cung cấp cho bạn tên đầy đủ. –

+0

@Pasi cảm ơn, sẽ thay đổi việc triển khai của tôi –

+3

Trong .Net 4.5, bạn có thể sử dụng CallerMemberNameAttribute để lấy tên của người gọi. Xem https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx ... Sau đó bạn có thể quấn phần thân của hàm của bạn vào một hàm ẩn danh như trong ([CallerMemberName] string functionName = "") => {}. Các vấn đề với việc sử dụng phương pháp phản xạ như trong câu trả lời được chấp nhận là (1) chức năng có thể được gạch chân, và/hoặc (2) tên hàm có thể bị xáo trộn nếu nó không công khai và mã bị che khuất. – GreatAndPowerfulOz

Trả lời

268
StackTrace st = new StackTrace(); 
StackFrame sf = st.GetFrame (0); 

MethodBase currentMethodName = sf.GetMethod(); 

Hoặc, nếu bạn muốn có một phương pháp helper:

[MethodImpl(MethodImplOptions.NoInlining)] 
public string GetCurrentMethod() 
{ 
    StackTrace st = new StackTrace(); 
    StackFrame sf = st.GetFrame (1); 

    return sf.GetMethod().Name; 
} 

cập nhật với các khoản tín dụng để @stusmith.

+52

Ghi nhớ JIT là miễn phí đối với các phương thức nội tuyến, điều này có thể làm giảm tính năng này. Để buộc một phương thức không được gạch chân, hãy thêm thuộc tính [MethodImpl (MethodImplOptions.NoInlining)]. – stusmith

+0

@stusmith: Cảm ơn! Sẽ nhớ nó! –

+0

@stusmith Cảm ơn –

415

Gọi System.Reflection.MethodBase.GetCurrentMethod().Name từ trong phương thức.

+3

Điều này có phải từ nội tuyến? – Gusdor

+1

Nếu bạn tự hỏi cái nào nhanh hơn, Reflection hoặc StackTrace hãy kiểm tra điều này: https://stackoverflow.com/a/1348853/495455 –

+9

Để tiết kiệm thời gian của bạn, hãy truy cập liên kết ở trên: StackTrace nhanh hơn. – lll

9

Bạn cũng có thể sử dụng MethodBase.GetCurrentMethod() sẽ chặn trình biên dịch JIT khỏi nội tuyến mà phương thức được sử dụng.


Cập nhật:

Phương pháp này có chứa một thống kê ðặc biệt StackCrawlMark rằng từ hiểu biết của tôi sẽ chỉ định để trình biên dịch JIT rằng phương pháp hiện nay không nên được inlined.

Đây là cách giải thích của tôi về nhận xét liên quan đến hiện diện điều tra đó trong SSCLI. Nhận xét sau:

// declaring a local var of this enum type and passing it by ref into a function 
// that needs to do a stack crawl will both prevent inlining of the calle and 
// pass an ESP point to stack crawl to 
// 
// Declaring these in EH clauses is illegal; 
// they must declared in the main method body 
+0

Bạn có một tham chiếu giải thích cách 'GetCurrentMethod' ức chế JIT từ nội tuyến phương thức gọi không? – LukeH

+0

@Luke, tôi cập nhật câu trả lời của tôi với lý do tại sao tôi tin rằng phương pháp này sẽ ức chế nội tuyến. –

+0

Cảm ơn, điều đó rất thú vị, mặc dù nó không hoàn toàn rõ ràng với tôi cho dù nó ngăn cản nội tuyến của phương thức khai báo 'StackCrawlMark' cục bộ hay người gọi phương thức đó. – LukeH

65

Phản ánh có một sở trường để ẩn rừng cho cây. Bạn không bao giờ gặp sự cố khi nhận tên phương thức hiện tại một cách chính xác và nhanh chóng:

void MyMethod() { 
    string currentMethodName = "MyMethod"; 
    //etc... 
} 

Mặc dù công cụ tái cấu trúc có thể sẽ không tự động sửa chữa.

Nếu bạn hoàn toàn không quan tâm đến chi phí (đáng kể) của việc sử dụng Reflection sau đó phương pháp helper này nên có ích:

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

[MethodImpl(MethodImplOptions.NoInlining)] 
public static string GetMyMethodName() { 
    var st = new StackTrace(new StackFrame(1)); 
    return st.GetFrame(0).GetMethod().Name; 
} 

Cập nhật: C# phiên bản 5 và .NET 4.5 có vàng giải pháp cho nhu cầu chung này, bạn có thể sử dụng [CallerMemberName] attribute để trình biên dịch tự động tạo tên của phương thức gọi trong đối số chuỗi. Các thuộc tính hữu ích khác là [CallerFilePath] để trình biên dịch tạo đường dẫn tệp mã nguồn và [CallerLineNumber] để lấy số dòng trong tệp mã nguồn cho câu lệnh đã thực hiện cuộc gọi.


Update2: cú pháp tôi đề nghị ở đầu câu trả lời bây giờ có thể được thực hiện để làm việc trong C# phiên bản 6 mà không có một công cụ refactoring ưa thích:

string currentMethodName = nameof(MyMethod); 
+0

Tôi đã làm điều này trước đây. Có thể là một sod để duy trì nếu bạn làm điều này ứng dụng rộng, nhưng nếu không: nhịp đơn giản thông minh bất cứ ngày nào! –

+2

Từ đúng, nhanh hơn khoảng 10.000 lần, đưa ra hoặc lấy hệ số 10. –

+12

+1 cho đầu đề [CallerMemberNameAttribute] .NET 4.5. Cảm ơn. –

4

Vâng System.Reflection.MethodBase.GetCurrentMethod().Name không phải là một lựa chọn rất tốt vì nó sẽ chỉ hiển thị tên phương pháp không có thông tin bổ sung.

Thích cho string MyMethod(string str) thuộc tính trên sẽ chỉ trả lại MyMethod không đủ.

Nó là tốt hơn để sử dụng System.Reflection.MethodBase.GetCurrentMethod().ToString() đó sẽ trả lại toàn bộ chữ ký phương pháp ...

+0

Tôi nhận được MoveNext thay vì tên phương thức của mình. –

23

Tôi nghĩ rằng cách tốt nhất để có được tên đầy đủ là:

this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name; 

hoặc thử này

string method = string.Format("{0}.{1}", MethodBase.GetCurrentMethod().DeclaringType.FullName, MethodBase.GetCurrentMethod().Name); 
+0

+1 vì việc sử dụng sự phản chiếu nhanh hơn nhiều so với việc sử dụng StackTrace. –

+4

Điều này không hoạt động đối với các phương thức 'async'. Tôi gọi 'System.Reflection.MethodBase.GetCurrentMethod(). Name' trên dòng đầu tiên của một phương thức và tôi nhận' MoveNext'. – Gusdor

+1

Có thể tạo hàm sẽ trả về tên/tên hàm của người gọi không? Giải pháp của bạn là tuyệt vời, nhưng một chút dài để được gọi là mỗi lần.Nó sẽ là lý tưởng nếu điều này có thể được trên một số lớp khác và chức năng công cộng hoặc có lẽ tài sản công cộng có thể được gọi. Lý tưởng nhất là ở một số lớp tĩnh. – FrenkyB

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