2015-02-03 14 views
9

Trong ứng dụng VB.NET của tôi, sự kiện AppDomain.CurrentDomain.AssemblyResolve có một trình xử lý đã đăng ký với nó. ResolveEventHandler được đăng ký sự kiện này đã được thêm vào từ mã của tôi (cho tất cả những gì tôi biết, System.AppDomainPrivate Method riêng của mình được đăng ký sự kiện) ... có thể Xóa tất cả trình xử lý khỏi sự kiện này để tôi có thể thêm xử lý của riêng bạn và đảm bảo đó là chỉ một?Có thể loại bỏ một VB.NET EventHandler mà lớp học của bạn đã không thêm?

Về cơ bản tôi đang cố gắng để làm điều này:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ClassX.MethodX 

Nhưng tôi không biết những gì ClassX hoặc MethodX là trong ví dụ này bởi vì tôi chưa thêm một handler cho sự kiện này nêu ra, và handler này đã được thêm vào bởi mã ngược dòng. Tôi đang sử dụng phương pháp mô tả ở đây để kiểm tra sự kiện nếu có xử lý được đăng ký: https://stackoverflow.com/a/2953318/734914

Edit: tôi đã có thể tìm ra những phương pháp được đăng ký với sự kiện này, bằng cách sử dụng cửa sổ ngay khi gỡ lỗi.

? DirectCast(gettype(System.AppDomain).GetField("AssemblyResolve", BindingFlags.Instance or BindingFlags.NonPublic).GetValue(AppDomain.CurrentDomain) , ResolveEventHandler) 
{System.ResolveEventHandler} 
    _methodBase: Nothing 
    _methodPtr: 157334028 
    _methodPtrAux: 1827519884 
    _target: {System.ResolveEventHandler} 
    **Method: {System.Reflection.Assembly ResolveAssembly**(System.Object, System.ResolveEventArgs)} 
    Target: Nothing 

Bây giờ tôi đang cố gắng để loại bỏ nó, như thế này, bởi vì nó không phải là một phương pháp công cộng:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly") 

Nhưng đó đưa ra một lỗi biên dịch nói: "AddressOf tham số phải là tên của một phương pháp". Vì vậy, tôi không chắc chắn làm thế nào để xác định một phương pháp phi công ở đây

+0

Không, không thể thực hiện điều đó. –

+0

là ứng dụng winforms này hay một lớp lib? – Plutonix

+0

mã của tôi là trong một ClassLibrary được nạp bởi một ứng dụng WinForms – plukich

Trả lời

1

Từ những nhận xét ban đầu:

Here's một chủ đề về loại bỏ các đại biểu từ các sự kiện bạn không có chữ ký đại biểu để .. khá tiện dụng, nhưng cuối cùng, người đăng ký đã nêu

"Có vẻ như AppDomain.CurrentDomain.AssemblyResolve không hỗ trợ xóa các sự kiện sao cho mã tôi đăng sẽ không hoạt động".

Thậm chí NET phàn nàn rằng sự kiện System.AppDomain.AssemblyResolve chỉ có thể xuất hiện ở phía bên tay trái của += hoặc -= (+=/-= nhà khai thác đang C# AddHandler/RemoveHandler) .. vì vậy nó trông giống như một 'không':/

Thêm vào đó, sau khi chỉnh sửa của bạn, lý do bạn không thể làm như sau:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly") 

là bởi vì từ khóa AddressOf là một từ khóa nhà điều hành, tương tự như một + hoặc - là một toán tử, các AddressOf hoạt động trên thủ tục được đưa ra và nó phải là một tên thủ tục nó có thể suy ra tại thời gian biên dịch. Và hàm GetMethod trả về loại MethodInfo và không phải là địa chỉ hàm đã biết.

Tất cả sẽ không bị mất!

Các AddHandlerRemoveHandler chức năng thực sự gọi cho một ObjectDelegate để được thông qua trong (AddressOf được biên dịch vào một Delegate khi sử dụng), vì vậy bạn không cần AddressOf để làm những gì bạn muốn, bạn cần có một .

Để làm điều này, chúng tôi có thể sử dụng phương pháp CreateDelegate làm chụp đối tượng MethodInfo. Cần lưu ý rằng kể từ khi bạn đang cố gắng truy cập vào các phương pháp riêng, bạn sẽ cần phải xác định BindFlags của Reflection.BindingFlags.InstanceReflection.BindFlags.NonPublic (tôi nói and nhưng bạn sẽ làm một Bitwise Or trên chúng), ví dụ:

GetType(Reflection.Assembly).GetMethod("ResolveAssembly", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic) 

vì vậy, gọi CreateDelegate về vấn đề này sẽ cho chúng ta đoạn mã sau

[Delegate].CreateDelegate(GetType(Reflection.Assembly), GetType(Reflection.Assembly).GetMethod("ResolveAssembly", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)) 

Nhưng đó là khá dài dòng, vì vậy cho phép phá vỡ nó xuống:

Dim type As Type = GetType(Reflection.Assembly) 
Dim mi As Reflection.MethodInfo = type.GetMethod("ResolveAssembly", (Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)) 

Và bây giờ chúng tôi chỉ có thể gọi RemoveHandler trên AppDomain.CurrentDomain.AssemblyResolve qua như sau:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, [Delegate].CreateDelegate(type, mi) 

Trừ AppDomain.CurrentDomain.AssemblyResolve hy vọng ủy/chữ ký sự kiện để phù hợp, vì vậy chúng tôi cần phải cast đại biểu tạo của chúng tôi để loại thích hợp:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, CType([Delegate].CreateDelegate(type, mi), System.ResolveEventHandler) 

Và bây giờ bạn có thể xóa phương thức riêng thông qua phản chiếu từ trình xử lý sự kiện.

CẢNH BÁO !! Trong khi mã này sẽ biên dịch và chạy, tôi không đảm bảo hiệu lực hoặc tính chính xác của nó vì bạn đang mucking với khung và con trỏ ngăn xếp (chủ yếu), và như vậy trong khi nó sức chạy và nó sức làm việc, nó cũng có thể đẻ trứng mèo con .. vì vậy hãy cẩn thận.

Hy vọng điều đó có thể hữu ích!

+0

Cảm ơn bạn txtechhelp :) – raed

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