2013-06-18 14 views
8

Tôi thậm chí không chắc chắn nếu điều này là có thể xin lỗi nếu không. Tôi đã googled khá rộng rãi và không tìm thấy những gì tôi đang tìm kiếm.Phương pháp ghi đè trong DLL bằng cách sử dụng sự phản chiếu

Về cơ bản, chúng tôi có một ứng dụng được sản xuất bởi bên thứ ba, trong đó, hoàn toàn thẳng thừng là rác rưởi. Chúng tôi có một vấn đề cụ thể và đã quản lý để theo dõi vấn đề bằng cách sử dụng ILSpy cho một phương pháp trong một DLL. Rõ ràng là chúng tôi không có (cũng không thể nhận được) mã nguồn và công ty được đề cập là không sẵn sàng khắc phục vấn đề trong bất kỳ thời điểm hợp lý nào.

Vì vậy, chúng tôi đã điều tra nhiều con đường điều tra khác nhau và không có gì. Tôi đã nhìn vào xem liệu điều này có thể được thực hiện bằng cách sử dụng sự phản ánh và điều này là khá nhiều hy vọng cuối cùng chúng ta có để làm việc này. Tóm lại, những gì tôi muốn làm là như sau:

  • Tạo một thư viện lớp đơn giản với tên giống như DLL hiện
  • Sử dụng phản ánh để nhập khẩu các phương pháp từ DLL hiện
  • Bằng cách nào đó ghi đè lên phương pháp được đề cập với chính mã của tôi, hãy sửa mã số
  • Tạo lại mã, vì vậy tôi có một DLL mới, chứa 99% chức năng của DLL hiện tại nhưng với mã ghi đè của tôi cung cấp chức năng chính xác.

Tôi đã tìm thấy, trong quá trình điều tra của tôi TypeBuilder.DefineMethodOverride và cũng là một trang từ StackOverflow, có vẻ tương tự nhưng không hoàn toàn những gì tôi đang tìm kiếm.

http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.definemethodoverride.aspx

Is there a way to "override" a method with reflection?

Bất cứ lời khuyên đánh giá cao!

Andrew

Sửa

Ý tưởng có thể khác tôi có là để tạo ra một lớp học phần có chứa các chức năng ghi đè lên, nhưng điều đó không có vẻ khả thi một trong hai.

+0

Tự hỏi nếu một cách tiếp cận dựa trên đánh chặn sẽ hoạt động ở đây - một cái gì đó như Castle DynamicProxy: http://www.castleproject.org/projects/dynamicproxy/ - rõ ràng là bạn sẽ không hoàn toàn thay thế cuộc gọi phương thức, nhưng bạn chắc chắn có thể chặn/lỗi xử lý và tinh chỉnh (oh yeah và nó phụ thuộc nếu lớp đó có các phương thức ảo) – Charleh

+0

Tại sao không chỉ tạo một lớp, như bạn đã nói, gọi lớp thứ ba cho hầu hết mọi thứ ngoại trừ phương thức bạn muốn ghi đè? Hoặc bắt nguồn từ lớp đó và sử dụng tên khác cho phương pháp đó? Ngoài ra bạn có thực sự cần điều đó để được bên trong 1 dll độc đáo? Tại sao không chia nó thành 2? – ppetrov

Trả lời

6

Bạn chỉ có thể ghi đè phương thức nếu nó là ảo và không quan trọng bạn có làm điều đó thông qua phản xạ hay tĩnh hay không. Tôi sẽ đề nghị sử dụng một trình dịch ngược (có rất nhiều cái miễn phí có sẵn) và sửa mã trong MSIL. Sau đó, bạn có thể tạo một assembly mới từ MSIL.

+0

Vâng, tôi vừa kiểm tra và phương pháp không phải là ảo, vì vậy đó là một ý tưởng trong cửa sổ. Tôi chỉ kiểm tra decompilers bây giờ - cảm ơn lời khuyên của bạn. – Andrew

+0

Làm thế nào về các dấu hiệu và publickeytoken? nó vẫn giữ nguyên? –

+0

Nếu DLL được ký (nó có tên mạnh) thì sau khi sửa đổi bạn cần phải từ chức nó với chứng chỉ của tên mạnh. –

0

Tôi nghĩ ý tưởng đầu tiên của bạn là tốt. Nếu lớp bên thứ ba không phải là sealed, bạn có thể lấy được từ đó và thêm phương thức của riêng bạn bằng một tên khác để sửa hành vi sai. Nếu bạn cần nó trong 1 dll, bạn có thể sử dụng IlMerge.

Nếu lớp bên thứ ba của bạn được niêm phong, bạn chỉ có thể có một thể hiện của lớp bên thứ ba này trong lớp mới của bạn và gọi các phương thức khi cần.

Nhưng bạn sẽ phải kiểm tra xem phương pháp nào bạn muốn "ghi đè" không được gọi bên trong thư viện đó, bởi vì nếu nó là giải pháp này sẽ không hoạt động ...

Nó không phải rất sạch sẽ, nhưng nó có thể là giải pháp tạm thời trong thời gian công ty chỉnh sửa thư viện khắc phục sự cố.

Và khi cố định, bạn chỉ cần đổi tên phương thức bạn sử dụng, vì vậy sẽ không mất thời gian.

0

Từ những gì bạn đã mô tả, tôi khuyên bạn nên sửa đổi cụm ban đầu. Quá trình này về cơ bản

  • là Decompile lắp ráp thành MSIL, C# hoặc bất cứ ngôn ngữ bạn nên chọn
  • Sửa đổi lắp ráp decompiled để bao gồm những thay đổi của bạn
  • biên dịch lại lắp ráp bằng cách sử dụng nguồn biến đổi

Từ những gì tôi có thể thấy Reflexil cho phép bạn làm điều đó, mặc dù nó có thể yêu cầu bạn mua Resharper (Tôi đã không tự mình thử)

Hoặc bạn có thể sử dụng ILDasm để dịch ngược toàn bộ hội đồng thành một tệp, sửa đổi tệp và sau đó biên dịch lại nó bằng cách sử dụng ILAsm

0

Tôi biết mình đến trễ một chút, nhưng tôi đồng ý với Charleh; nếu bạn có một lớp học không hoạt động tốt và không có lợi cho việc thay thế, nhưng ít nhất tuyên bố các phương thức của nó là virtual, thì bạn sẽ gặp may. Sau đây sử dụng tài liệu tham khảo để Castle.CorePatterns:

var interceptor = new DelegateInterceptor(proceed: call => 
{ 
    if(ShouldCallProceed(call)) call.Proceed(); 
    else AlternativeLogic(); 
}); 

var generator = new ProxyGenerator(); 
var proxy = generator.CreateClassProxy<UncooperativeType>(interceptor); 

proxy.RubbishMethod(); 

Tôi cũng đã lấy sự tự do cung cấp a running sample of this trong LinqPad. Nó cho thấy sự khác biệt giữa các phương pháp cho phép chặn (virtual) và các phương thức không cho phép chặn. Nó cũng cho thấy một cách hữu ích để bẫy các ngoại lệ mà không cần tất cả mã sử dụng Try.Do từ Patterns.