2011-11-12 41 views
10

Tôi đang sử dụng Mono.Cecil để tạo một assembly có chứa một lớp dẫn xuất ghi đè một phương thức cụ thể trong một lớp cơ sở đã nhập. Phương pháp ghi đè là ghi đè 'ẩn'. Vấn đề là tôi không thể tìm ra cách chỉ định nó như là một sự ghi đè.Cách tạo phương thức ghi đè bằng Mono.Cecil?

Tôi đang sử dụng mã sau để tạo phương pháp ghi đè.

void CreateMethodOverride(TypeDefinition targetType, 
     TypeDefinition baseClass, string methodName, MethodInfo methodInfo) 
    { 
     // locate the matching base class method, which may 
     // reside in a different module 
     MethodDefinition baseMethod = baseClass 
      .Methods.First(method => method.Name.Equals(methodName)); 

     MethodDefinition newMethod = targetType.Copy(methodInfo); 
     newMethod.Name = baseMethod.Name; 
     newMethod.Attributes = baseMethod.Attributes; 
     newMethod.ImplAttributes = baseMethod.ImplAttributes; 
     newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes; 
     targetType.Methods.Add(newMethod); 
    } 

Đó là sự hiểu biết của tôi rằng một override ngầm phải có chữ ký giống như phương pháp di truyền. Sử dụng mã trên, khi tôi xem phương thức kết quả trong Reflector, lớp cơ sở và các phương thức lớp dẫn xuất có cùng chữ ký chính xác, cụ thể là "public virtual void f (int param)".

tôi đã cố gắng loại bỏ các thuộc tính rõ ràng "ảo", nhưng sau đó các phương pháp có nguồn gốc kết thúc lên như "public void f (int param)'.

Làm thế nào để có được phương pháp có nguồn gốc có đúng" public override void f (int param)" chữ ký

LƯU Ý: tôi có một phương pháp khuyến nông ('TypeDefinition.Copy') mà bắt chước một MethodInfo và trả về một MethodDefinition bằng cách nhập tất cả các loại tham chiếu vv

Trả lời

10

Trong lớp cơ sở của bạn, giả sử bạn tạo ra phương pháp sau:

public virtual void f(int); 

Bạn phải đảm bảo rằng cờ có cờ IsVirtual được đặt thành true. Bạn cũng phải đảm bảo rằng nó có cờ IsNewSlot = true, để đảm bảo rằng nó có một vị trí mới trong virtual method table.

Bây giờ, đối với các phương pháp ghi đè, bạn muốn tạo:

public override void f(int); 

Để làm như vậy, bạn cũng cần phải có phương pháp để được IsVirtual, mà còn để nói với nó rằng nó không phải là một phương pháp ảo mới , nhưng nó ngầm ghi đè lên một cái khác, vì vậy bạn phải làm cho nó .IsReuseSlot = true.

Và bởi vì bạn đang sử dụng ghi đè ngầm, bạn cũng phải đảm bảo cả hai phương pháp là .IsHideBySig = true.

Với tất cả các thiết lập đó, bạn nên có phương pháp ghi đè thích hợp.

+0

Cảm ơn thông tin - chính xác những gì tôi cần. Vì một số lý do, tôi không nhận được thông báo qua email từ SO hoặc nhóm Mono-Cecil. Xin lỗi vì đã hỏi qua nhiều kênh! –

+0

Không sao, chúng tôi đã tìm được giải pháp cho vấn đề của bạn! –

7

Vì lợi ích của độc giả khác, đây là kết quả cuối cùng thu được bằng cách làm theo câu trả lời của JB:

void CreateMethodOverride(TypeDefinition targetType, 
    TypeDefinition baseClass, string methodName, MethodInfo methodInfo) 
{ 
    MethodDefinition baseMethod = baseClass 
     .Methods.First(method => method.Name.Equals(methodName)); 

    MethodDefinition newMethod = targetType.Copy(methodInfo); 
    newMethod.Name = baseMethod.Name; 

    // Remove the 'NewSlot' attribute 
    newMethod.Attributes = baseMethod.Attributes & ~MethodAttributes.NewSlot; 

    // Add the 'ReuseSlot' attribute 
    newMethod.Attributes |= MethodAttributes.ReuseSlot; 

    newMethod.ImplAttributes = baseMethod.ImplAttributes; 
    newMethod.SemanticsAttributes = baseMethod.SemanticsAttributes; 
    targetType.Methods.Add(newMethod); 
} 
Các vấn đề liên quan