2012-06-30 28 views
5

Tôi nhận thấy rằng .NET 4.5 có một thuộc tính mới được gọi là [CallerMemberNameAttribute], khi được gắn với tham số của phương thức, sẽ cung cấp tên chuỗi của phương thức được gọi là phương thức (nếu điều đó có ý nghĩa).C# Gọi phương thức mà không có dấu vết ngăn xếp

Tuy nhiên, thật không may (vì tôi muốn làm điều gì đó với XNA), tôi chỉ nhắm mục tiêu .NET 4.0.

Tôi muốn để có thể làm điều gì đó như:

void MethodA() { 
    MethodB(); 
} 

void MethodB() { 
    string callingMethodName = (...?); 
    Console.WriteLine(callingMethodName); 
} 

ở đâu ra tôi sẽ MethodA.

Tôi biết tôi có thể làm điều này thông qua theo dõi ngăn xếp, nhưng đó là a) Không đáng tin cậy và b) Sloooow ... Vì vậy, tôi tự hỏi nếu có bất kỳ cách nào khác để thu thập thông tin đó, tuy nhiên có thể ...

Tôi đã hy vọng cho bất kỳ ý tưởng hoặc kiến ​​thức mà bất cứ ai có thể có về vấn đề này. Cảm ơn trước :)

+3

Chuyển tên gọi phương thức làm chuỗi? – Oded

+2

@Oded Vâng có rõ ràng tôi có thể gọi MethodB ("MethodA") nhưng điểm là tôi đang cố gắng để làm điều đó tự động, vì vậy nếu tôi thay đổi MethodA để MethodC tôi không phải chỉnh sửa cuộc gọi đó là tốt. – Xenoprimate

+0

Bạn không thể thực hiện được điểm đó trong câu hỏi. – Oded

Trả lời

13

Nếu bạn sử dụng Visual Studio 2012 để biên dịch, bạn có thể tự viết CallerMemberNameAttribute và sử dụng nó theo cách tương tự với .NET 4.5 ngay cả khi bạn vẫn nhắm mục tiêu .NET 4.0 hoặc 3.5. Trình biên dịch sẽ vẫn thực hiện thay thế tại thời gian biên dịch, thậm chí nhắm mục tiêu một phiên bản khung cũ hơn.

Chỉ cần thêm dòng sau vào dự án của bạn sẽ làm các trick:

namespace System.Runtime.CompilerServices 
{ 
    public sealed class CallerMemberNameAttribute : Attribute { } 
} 
+0

Tôi chỉ là một lập trình viên hobbyist vì vậy xin lỗi nếu đây là một câu hỏi ngu ngốc, nhưng có cách nào tôi có thể nhìn thấy nguồn cho CallerMemberNameAttribute của Microsoft? Để sao chép nó, ý tôi là. – Xenoprimate

+2

Nói chung, có, bạn có thể dịch ngược các thư viện .NET bằng cách sử dụng ILSpy. http://wiki.sharpdevelop.net/ILSpy.ashx Tuy nhiên, các thuộc tính hiếm khi mang lại bất cứ điều gì thú vị, vì bit thú vị thường xuyên hơn trong cách nó được sử dụng bởi mã khác. Ví dụ. từ những gì @ReedCopsey nói, việc chuyển đổi được thực hiện tại thời gian biên dịch bởi trình biên dịch, chứ không phải bởi thuộc tính, và thậm chí bạn không cần thời gian chạy .NET 4.5, vì vậy bạn sẽ không thấy mã thú vị nào. –

+0

Ah, do đó, trình biên dịch chỉ nhìn thấy tên 'CallerMemberNameAttribute' và chèn logic riêng của nó?Nếu vậy, tôi chỉ có thể tạo một thuộc tính trống với tên đó và nó sẽ hoạt động? – Xenoprimate

0

Bạn có thể cung cấp tên gọi như một tham số cho phương thức gọi. Không khá gì bạn đang yêu cầu, nhưng nó hoạt động mà không cần phải truy cập vào stack frame:

[MethodImpl(MethodImplOptions.NoInlining)] 
void MethodA() 
{ 
    string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; 
    MethodB(methodName); 
} 

void MethodB(string callingMethodName) 
{ 
    Console.WriteLine(callingMethodName); 
} 

Bằng cách sử dụng MethodBase.GetCurrentMethod(), bạn có thể đảm bảo rằng việc thực hiện của bạn vẫn Refactor an toàn - nếu tên của những thay đổi phương pháp của bạn, kết quả sẽ vẫn chính xác.

Đừng quên đánh dấu phương thức gọi bằng MethodImplOptions.NoInlining để tránh phương thức nội tuyến.

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