2009-05-20 43 views
11

Khi sử dụng sự phản chiếu, có thể nhận được ngăn xếp cuộc gọi (ngoài ra nó có thể là một xấp xỉ thô do tối ưu hóa JIT) bằng cách sử dụng System.Diagnostics.StackTrace và kiểm tra các đối tượng StackFrame chứa.Làm thế nào để có được đối tượng thực hiện cho một stackframe?

Làm cách nào tôi có thể tham chiếu đến đối tượng (con trỏ này) mà phương thức trong khung ngăn xếp đang thực thi?

Tôi biết tôi có thể lấy MethodBase bằng cách gọi GetMethod() trên đối tượng khung ngăn xếp, nhưng những gì tôi đang tìm là một cái gì đó dọc theo dòng GetObject() (tự nhiên trả về null nếu phương thức là tĩnh). Dường như đối tượng khung ngăn xếp chỉ có thể được truy vấn cho thông tin được xác định tĩnh như thông tin phương pháp, tệp gốc, v.v.

Trình gỡ lỗi VS biết (mặc dù nó có thể sử dụng phương pháp khác để nhận dấu vết cuộc gọi), vì có thể nhấp đúp vào bất kỳ khung ngăn xếp nào trong cửa sổ ngăn xếp cuộc gọi và xem xét các giá trị của các trường địa phương và lớp.

EDIT: Để làm rõ: Tôi muốn đối tượng dụ trên mà phương pháp này được gọi. Tức là: Nếu phương thức Foo() được gọi trên cá thể đối tượng A ở đâu đó trên ngăn xếp cuộc gọi, và nó xếp vào phương thức tôi thực hiện theo dõi ngăn xếp, tôi muốn lấy tham chiếu đến A từ nơi tôi thực hiện theo dõi ngăn xếp. (Không phải là kiểu tuyên bố của các cơ sở phương pháp)

Trả lời

6

Tôi khá chắc chắn rằng điều này là không thể. Dưới đây là lý do:

  1. Điều này có thể phá vỡ kiểu an toàn, vì ai cũng có thể tra cứu một khung hình, lấy đối tượng bất kể là AppDomain \ Chủ đề họ đang thực hiện hoặc cho phép họ có.

  2. Các 'this' (C#) nhận dạng được thực sự chỉ là một cuộc tranh cãi với phương pháp dụ (đầu tiên), như vậy trong thực tế không có sự khác biệt giữa các phương pháp tĩnh và phương pháp dụ, trình biên dịch thực hiện magic của nó để vượt qua bên phải this với một phương thức thể hiện, tất nhiên có nghĩa là bạn sẽ cần phải có quyền truy cập vào tất cả các đối số phương thức để lấy đối tượng this. (Mà StackFrame không hỗ trợ)

Nó có thể là có thể bằng cách sử dụng unsafe mã để có được con trỏ của đối số đầu tiên một phương pháp dụ và sau đó đúc nó vào đúng chủng loại, nhưng tôi không có kiến ​​thức về cách để làm điều đó, chỉ là một ý tưởng.

BTW bạn có thể tưởng tượng các phương pháp ví dụ sau khi được biên dịch giống như phương pháp mở rộng C# 3.0, chúng có được con trỏ this làm đối số đầu tiên của chúng.

+0

Tôi biết rằng con trỏ này được chuyển đến được gọi là phương thức trên ngăn xếp cuộc gọi bởi người gọi, đó là lý do tại sao GetObject không tồn tại() sẽ trả về null nếu nó là một phương thức tĩnh và một bản sao của con trỏ 'this' chuẩn trong một phương thức instance. Tuy nhiên, tôi đồng ý với đối số số 1 của bạn, ngoại trừ việc quyền truy cập vào đối tượng có thể dễ dàng bị hạn chế bằng cách yêu cầu sự cho phép thích hợp theo thiết kế. –

+0

Vấn đề thực sự là một StackFrame chỉ là một số siêu dữ liệu về mã của bạn, nó không phải là một phiên bản trực tiếp của mã của bạn. – Yona

+0

Như tôi lo sợ. Nhưng tôi hy vọng có một số lớp khác để tận dụng. –

-1

Tôi không chắc chắn rằng tôi hoàn toàn hiểu những gì bạn muốn, nhưng nếu bạn muốn biết các loại, trong đó phương pháp cho một stack frame nào đó được công bố, tôi nghĩ rằng mã này trả rằng:

StackTrace trace = new StackTrace();  
Type methodOwner = trace.GetFrame(0).GetMethod().DeclaringType; 

bạn sẽ tất nhiên cần phải vượt qua các chỉ số cho khung mà bạn quan tâm (tôi sử dụng 0 như ví dụ).

+2

Tôi nghĩ rằng anh ấy ngụ ý ví dụ, không phải loại. –

+0

Vâng, 'đối tượng' có nghĩa là trường hợp của một loại;) –

+0

Có, tôi nhận ra rằng (nó thực sự khá rõ ràng trong câu hỏi của bạn; Tôi hơi mệt một chút) ... –

3

Có thể tham chiếu đến thiscall đối tượng, nhưng không phải chỉ với mã .NET. Mã gốc phải được tham gia. Ngay cả khi sử dụng các lớp động và không gian tên System.Relection.Emit .NET không có các công cụ để truy cập vào một chồng và các đối số đánh giá phương thức khác.

Ở phía bên kia nếu bạn tháo rời phương pháp .NET của mình, bạn có thể thấy rằng tham chiếu này không được chuyển vào chồng vật lý. Thiscall tài liệu tham khảo được lưu trữ trong ECX (RCX cho x64) đăng ký thay thế. Vì vậy, nó có thể leo lên trên stack từ phương pháp của bạn để phương pháp mà từ đó bạn muốn có được thiscall đối tượng. Và sau đó tra cứu bên trong các mã máy của phương thức đó để biết hướng dẫn tiết kiệm ECX (RCX) trong ngăn xếp và nhận được từ địa chỉ tương đối lệnh đó nơi tham chiếu đó nằm.

Tất nhiên, phương pháp leo rất khác nhau trong ứng dụng x32 và x64. Để tạo ra chức năng như vậy, bạn phải sử dụng không chỉ C# nhưng mã lắp ráp, và ghi nhớ rằng lắp ráp nội tuyến không được phép theo x64; nó phải là một mô-đun lắp ráp đầy đủ.

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