Tôi đang phát xung quanh với API phản chiếu C#. Tôi có thể dễ dàng tải thông tin Type
của các lớp học, phương pháp, vv trong một hội đồng, tuy nhiên, bây giờ tôi tự hỏi làm thế nào tôi có thể tải và đọc mã bên trong một phương pháp?Tôi có thể sử dụng sự phản chiếu để kiểm tra mã trong một phương thức không?
Trả lời
Basic Trả lời:
Bạn không thể với hàm phản chiếu (System.Reflection).
Lý do là api phản chiếu được thiết kế để hoạt động trên Siêu dữ liệu (Loại lớp, Tên và Chữ ký của phương pháp, ...) nhưng không ở cấp dữ liệu (chính là chính dòng IL).
Extended Trả lời:
Bạn có thể phát ra (nhưng không đọc) IL với System.Reflection.Emit (ví dụ ILGenerator Class).
Thông qua MethodInfo.GetMethodBody()
bạn có thể nhận luồng nhị phân IL để triển khai phương thức. Nhưng điều đó thường hoàn toàn vô dụng bởi chính nó.
Có thư viện bên ngoài (như Cecil) mà bạn có thể sử dụng để đọc/sửa đổi/thêm/xóa mã bên trong một phương thức.
Bạn không thể tham khảo phương pháp thông qua một đại biểu, sau đó tạo một ExpressionTree từ đại biểu và kiểm tra cây? –
@Matt Greer: Không. Bạn không thể "đảo ngược kỹ sư" phần thân phương thức của một đại biểu thành một cây biểu thức. – LBushkin
@Matt: Điều đó sẽ không cung cấp cho bạn mã * bên trong * phương thức, bạn sẽ chỉ nhận được 'MethodCallExpression' cung cấp cho bạn quyền truy cập vào cùng một' MethodInfo' mà bạn có thể nhận được trực tiếp hơn với API phản chiếu. – Aaronaught
Không
Đây là tính năng được sắp xếp cho phiên bản tiếp theo của C#. Bạn có thể sử dụng CodeDom để có được nhiều thông tin hơn so với sự phản chiếu, nhưng bạn không thể thẩm vấn cây phân tích được.
Cũng luôn có mono, trong trình biên dịch đơn là một dịch vụ và bạn có thể nhận được các cây phân tích khi chạy.
Câu hỏi hay hơn là tại sao bạn muốn?
Có, phải có cách để đạt được điều này: Công cụ .NET Reflector cũng thực hiện điều này. Tuy nhiên, không thể nói cho bạn biết nó được thực hiện như thế nào.
Tại sao bạn không phản ánh phản xạ;) – ntziolis
Phản xạ không sử dụng phản ánh ít nhất là không có trong khuôn khổ .NET. Nó thực sự phân tích cú pháp tệp PE và phân tích mã IL từ phần .TEXT. Sau đó, một số mô hình rất thông minh và mát mẻ phù hợp với bản đồ/dịch ngược IL trở lại một ngôn ngữ đích. –
Nếu bạn không cần thực hiện việc này theo thời gian thực, hãy xem Reflector. Bạn có thể tháo rời bất kỳ hội đồng .NET nào (bao gồm cả các DLL lõi MS) và xem mã bằng ngôn ngữ bạn chọn. Đây có thể là rất giáo dục.
Cập nhật Có ai đã thử sử dụng Reflector on Reflector để tìm hiểu cách thực hiện việc này không?
Lưu ý, điều này không khử tối ưu mã. Vì vậy, nếu có một tối ưu hóa trình biên dịch được thực hiện cho IL, nó không được trả về nguồn xây dựng ban đầu của nó, nhưng với một phiên bản được tối ưu hóa bằng văn bản của con người ít hơn một chút.Đó là một cách gọn gàng để xem bạn có thể làm gì hiệu quả nhất. – DevelopingChris
Bạn không thể sử dụng Reflector on Reflector. Hãy thử nó và xem, bạn sẽ nhận được một bất ngờ tốt đẹp. – Aaronaught
Phản xạ được mã hóa sao cho nó không thể phản ánh trên chính nó, tôi nghĩ rằng họ đã sử dụng DotFuscator để làm điều đó. – DevelopingChris
Điều đó tùy thuộc vào ý bạn bằng cách đọc mã. Có 4 dạng mã.
1- Mã nguồn ví dụ: bản gốc C# hoặc VB.NET - Không, bạn không thể có được điều này với sự phản ánh
2- Các biểu tượng mã IL - Không, bạn không thể có được điều này với sự phản ánh
3- mã lắp ráp JITed - Không, bạn không thể có được điều này với sự phản ánh
4- Các byte IL, các byte thực mà IL được biên dịch thành, điều này bạn có thể nhận được.
Hãy xem phương thức MethodBase.GetMethodBody(), bạn có thể nhận các byte IL, các biến cục bộ, khung ngoại lệ, v.v. http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getmethodbody.aspx
'GetMethodBody()' là gần nhất bạn có thể nhận được, tôi nghĩ. – LBushkin
Bạn loại có thể. Hàm có liên quan là MethodBase.GetMethodBody.
Đây không phải là API hữu ích nhất. Bạn có thể nhận được một số thông tin cơ bản về những gì bên trong phương thức, và bạn có thể lấy IL làm mảng byte. Đó là về nó.
Có một API tốt hơn một chút trong Mono.Cecil thư viện, trong đó cho thấy một lớp MethodDefinition
với MethodBody
thực hiện riêng của mình, trong đó có thực tế Instructions
, vì vậy bạn không cần phải giải thích mã byte thô. Tuy nhiên, nếu bạn đang tìm kiếm để có được mã C# ra khỏi nó à la Reflector, bạn sẽ rất thất vọng. Ngoài ra, Cecil cũng không được tài liệu.
Nếu bạn vẫn muốn thử, thì chúc may mắn.
Hiện nay có thư viện/gói cho phép bạn kiểm tra mã phương pháp và thậm chí dịch ngược nó để Expression
:
- 1. Java: Cách kiểm tra xem một phương pháp có bị ghi đè hay không, sử dụng phản chiếu
- 2. Android/Java: Gọi phương thức sử dụng phản chiếu?
- 3. Gọi phương thức tĩnh sử dụng phản chiếu
- 4. Làm cách nào để kiểm tra xem phương pháp có tĩnh hay không bằng cách sử dụng phản chiếu?
- 5. Không bao giờ sử dụng sự phản chiếu trong mã sản xuất! Điều gì về Python?
- 6. Không thể giảm độ phức tạp của chu trình trong phương thức Nhà máy mà không sử dụng phản chiếu
- 7. Tại sao tôi nhận được "đối tượng không phải là một thể hiện khai báo lớp" khi gọi một phương thức sử dụng sự phản chiếu?
- 8. Lấy tên hàm sử dụng sự phản chiếu trong Golang
- 9. Tạo phương thức động để đặt trường của cấu trúc thay vì sử dụng phản chiếu
- 10. Tôi có thể kiểm tra xem trình biên dịch C# có nêu một lời gọi phương thức không?
- 11. Làm thế nào để gọi một phương thức đối tượng Scala bằng cách sử dụng sự phản chiếu?
- 12. Phương pháp ghi đè trong DLL bằng cách sử dụng sự phản chiếu
- 13. Sử dụng phản chiếu, gọi phương thức của một Trường trên đối tượng đã tồn tại
- 14. Giải mã giao thức phản chiếu AirPlay
- 15. Các ngoại lệ phản chiếu và kiểm tra Java
- 16. Phản chiếu có thực sự chậm không?
- 17. Có cách nào tốt đẹp để tránh sử dụng sự phản chiếu để điền vào ListView ảo của tôi không?
- 18. Làm thế nào tôi có thể ghi đè lên các phương thức trong Java khi tôi tạo một đối tượng thông qua sự phản chiếu?
- 19. Có thể lấy phương thức tham chiếu trong VB.NET không?
- 20. Làm thế nào để phát hiện modifer "mới" trên một trường sử dụng sự phản chiếu?
- 21. Làm thế nào tôi có thể kiểm tra một đối tượng bên trong một phương thức trong Objective-C?
- 22. Lấy danh sách các phương pháp có thể truy cập cho một lớp học đã cho qua sự phản chiếu
- 23. Trong Java, làm thế nào để sử dụng sự phản chiếu để có được một phương thức tĩnh và thực thi nó?
- 24. tại sao tôi không thể tải thuộc tính AssemblyVersion bằng cách sử dụng phản chiếu?
- 25. Ruby: Tôi có thể sử dụng các phương thức ví dụ bên trong một phương thức lớp không?
- 26. Mã Java Sử dụng Trình kiểm tra
- 27. Sử dụng sự phản chiếu để tạo ra biểu thức lambda như x => new {..}
- 28. C# đơn vị kiểm tra: Kiểm tra một phương pháp có sử dụng MapPath
- 29. Tôi có thể sử dụng thread.stop() trong Java nếu tôi thực sự cần nó không?
- 30. Làm thế nào để tạo ra một thể hiện của enum bằng cách sử dụng sự phản chiếu trong java?
gì kịch bản có hữu ích không? Nó phá vỡ một trong những người thuê nhà cơ bản của OO là đóng gói. Nhưng hơn nữa mã như IL không thực sự giống nhau. – DevelopingChris
@DevelopingChris: Nếu bạn đang viết một trình gỡ rối hoặc công cụ phân tích mã, nó có thể hữu ích để có thể tải một assembly và phân tích phần thân của một phương thức. Đây là, trên thực tế, những công cụ như FxCop làm. – LBushkin
Đối tượng mục tiêu của .NET là các tập đoàn Mỹ (và thứ hai có lẽ là một số doanh nghiệp nhỏ). Nếu bạn có thể bỏ qua .NET obfuscation, phần mềm (đắt tiền để sản xuất) có thể dễ dàng bay vào đầu ngón tay của một đối thủ cạnh tranh. – micahhoover