Domanda

Un esempio spiega meglio :

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();

}

Mi sarei aspettato l'uscita:

Intercepted foo
foo
Intercepted bar
bar

Invece, ottengo:

Intercepted foo
foo
bar

Perché?

Come funziona il dynamic proxy lavoro?Mi aspettavo il proxy generato per ereditare da proxy di classe, tuttavia, sembra che la utilizza composizione di delegare ciascuno dei metodi approssimati di interfaccia per l'effettiva attuazione.

Ho provato con il Castello DynamicProxy e anche con una vecchia dynamic proxy attuazione, da Cramon

È stato utile?

Soluzione

Sembra la mia ipotesi era giusta.

Ho provato lo stesso esempio, solo che questa volta la creazione di proxy direttamente dal tipo di classe:

Main(){

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

}

Il risultato è stato quello che mi aspettavo, in primo luogo:

Intercepted foo
foo
Intercepted bar
bar

Questo mi porta alla seguente conclusione:

  • durante la creazione di un proxy da un'interfaccia, utilizza composizione per delegare le chiamate per l'attuazione
  • durante la creazione di un proxy da un (classe) tipo di eredita il tipo, in modo virtuale chiama il tipo di classe provvederà a chiamare i metodi ridefiniti nel proxy.

Durante la creazione di un proxy di interfaccia con un'implementazione dell'interfaccia, proxy generata sembra qualcosa di simile a questo:

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();
  }
}

Durante la creazione di una classe proxy, il codice simile a questo:

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();
  }
}

Altri suggerimenti

Si sta utilizzando il metodo CreateInterfaceProxyWithTarget che istruisce il costruttore proxy per creare un proxy per l'interfaccia e inoltrare le chiamate verso l'oggetto di destinazione, in modo da quello che stai vedendo è quello che hai chiesto di fare.

Se si desidera che il proxy per derivare dalla classe allora avresti bisogno di utilizzare il metodo CreateClassProxy invece.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top