2010-04-22 24 views
33

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?

+0

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

+8

@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

+0

Đố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

Trả lời

31

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.

+1

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? –

+1

@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

+0

@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

1

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?

1

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.

+1

Tại sao bạn không phản ánh phản xạ;) – ntziolis

+9

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. –

2

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?

+1

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

+0

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

+1

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

16

Đ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

+0

'GetMethodBody()' là gần nhất bạn có thể nhận được, tôi nghĩ. – LBushkin

9

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.

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