2010-01-28 24 views
6

Một ví dụ giải thích nó tốt nhất:Tại sao bộ chặn đánh chặn DynamicProxy không được gọi cho mỗi cuộc gọi phương thức ảo?

public interface IA { 
    void foo(); 
    void bar(); 
} 

public class A : IA { 
    public virtual void foo(){ 
    Console.Write("foo"); 
    bar();     //call virtual method 
    } 
    public virtual void bar(){ 
    Console.Write("bar"); 
    } 
} 

public class Interceptor : IInterceptor { 
    public void Intercept(IInvocation invocation) 
    { 
    Console.WriteLine("Intercepted: " + invocation.Method.Name); 
    invocation.Proceed(); 
    } 
} 

Main(){ 
    IA a = new A(); 

     //proxy-ing an interface, given an implementation 
    IA proxy = new Castle.DynamicProxy.ProxyGenerator() 
       .CreateInterfaceProxyWithTarget(a, new Interceptor()); 
    proxy.foo(); 

} 

tôi dự kiến ​​sẽ có kết quả:

Intercepted foo 
foo 
Intercepted bar 
bar 

Thay vào đó, tôi nhận được:

Intercepted foo 
foo 
bar 

Tại sao?

Proxy động hoạt động như thế nào? Tôi hy vọng proxy được tạo là kế thừa từ lớp được ủy quyền, tuy nhiên, có vẻ như nó sử dụng thành phần để ủy quyền từng phương thức trong giao diện proxy với việc triển khai thực tế.

Tôi đã thử với Castle DynamicProxy và cũng với một thực hiện proxy năng động cũ, từ Cramon

Trả lời

9

Dường như đoán của tôi là đúng.

Tôi đã thử các ví dụ tương tự, chỉ có thời gian này tạo proxy trực tiếp từ kiểu lớp:

Main(){ 

    //proxy-ing an explicit type 
    A proxy = (A) new Castle.DynamicProxy.ProxyGenerator() 
       .CreateClassProxy<A>(new Interceptor()); 
    proxy.foo(); 

} 

Kết quả là những gì tôi mong đợi ở nơi đầu tiên:

Intercepted foo 
foo 
Intercepted bar 
bar 

Điều này dẫn tôi vào kết luận sau:

  • khi tạo proxy từ giao diện, nó sử dụng compos ition để ủy quyền các cuộc gọi đến việc triển khai
  • khi tạo proxy từ loại (lớp), nó thừa kế từ loại, vì vậy tất cả các cuộc gọi ảo trong loại lớp sẽ gọi các phương thức ghi đè trong proxy.

Khi tạo một proxy giao diện với một thực hiện giao diện, proxy được tạo ra trông giống như sau:

class InterfaceProxy: IA { //implements interface 
    IA m_impl; 
    [...] 

    Proxy(IA i_impl){ 
    m_impl = i_impl; 
    } 
    public void foo(){ 
    //overly-simplified, but you get the picture 
    InvokeInterceptors("foo"); 

    //execution gets here when calling 'invocation.Proceed()' 
    //from the interceptor 

    m_impl.foo(); //pass the execution to the implementation; 
        //the proxy has no more control over what gets executed. 

    } 
    public void bar(){ 
    InvokeInterceptors("bar"); 
    m_impl.bar(); 
    } 
} 

Khi tạo một proxy lớp, mã trông như thế này:

class ClassProxy: A { //inherits class type 

    Proxy(): base() { ... } 

    public override void foo(){ 
    InvokeInterceptors("foo"); 

    //execution gets here when calling 'invocation.Proceed()' 
    //from the interceptor 

    base.foo(); //pass the execution to the base class 

    } 
    public void bar(){ 
    InvokeInterceptors("bar"); 
    base.bar(); 
    } 
} 
+0

Vâng, đó là nhiều hay ít chính xác. –

+0

Chà, bạn là ngôi sao nhạc rock trong vũ trụ Castle DynamicProxy :) Cảm ơn bạn đã viết hướng dẫn! (hoặc tôi nên nói, * THE * hướng dẫn;) –

6

Bạn đang sử dụng phương pháp CreateInterfaceProxyWithTarget mà chỉ thị xây dựng proxy để tạo ra một proxy cho giao diện và chuyển tiếp cuộc gọi đến đối tượng mục tiêu, vì vậy những gì bạn thấy là những gì bạn đã yêu cầu.

Nếu bạn muốn proxy lấy được từ lớp học của bạn thì bạn cần sử dụng phương thức CreateClassProxy thay thế.

+0

tôi chỉ cần viết xong câu trả lời của riêng tôi khi tôi nhìn thấy bạn :) Vì vậy, có vẻ lý do của tôi là đúng. –

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