2010-06-17 11 views
7

Estoy tratando de implementar mi propia intercepción mientras sigo usando el contenedor de Unity. Quiero hacer esto de tal manera que respete el administrador de por vida utilizado. es decir, si se trata de un PerResolveLifetimeManager, entonces quiero envolver la instancia una vez y quiero que esa instancia envuelta se use durante la resolución.Unity Container: utilizando PerResolveLifetimeManager y la interceptación personalizada

Hasta ahora he implementado una estrategia BuilderStrategy que agrego a mi contenedor utilizando una clase UnityContainerExtension personalizada (paso PostInitialization al método AddNew; no estoy seguro de cuál es el valor más apropiado pero parece que funcionó). En una anulación de PostBuildUp en mi BuilderStrategy, reemplazo el contexto. Existe con mi valor empaquetado.

Cuando uso esto con la duración PerResolve, se produce un ajuste pero solo el primer uso de la dependencia obtiene la instancia envuelta y el resto obtiene una instancia no envuelta. es decir, si mi ctor capta IFoo foo1 y IFoo foo2, solo foo1 es mi instancia envuelta mientras que foo2 es la instancia desenvuelta.

Aquí es una repro muestra (por simplicidad, estoy usando una instancia de otra clase, Foo2, en vez del envoltorio):

public class MyInterception : UnityContainerExtension 
{ 
    protected override void Initialize() 
    { 
     Context.Strategies.AddNew<MyInterceptionStrategy>(UnityBuildStage.PostInitialization); 
    } 
} 

public class MyInterceptionStrategy : BuilderStrategy 
{ 
    public override void PostBuildUp(IBuilderContext context) 
    { 
     if (!context.OriginalBuildKey.Type.IsInterface) 
     { 
      return; 
     } 

     context.Existing = new Foo2(); 
    } 
} 

public class Bar 
{ 
    public Bar(IFoo f1, IFoo f2, IFoo f3) 
    { 
    } 
} 

public interface IFoo 
{ 
} 

public class Foo1 : IFoo 
{ 
} 

public class Foo2 : IFoo 
{ 
} 

public void Main() 
{ 
    UnityContainer container = new UnityContainer(); 
    container.AddNewExtension<MyInterception>(); 
    container.RegisterType(typeof (IFoo), typeof (Foo1), new PerResolveLifetimeManager()); 

    container.Resolve<Bar>(); 
} 

Si se pone un punto de interrupción en PostBuildUp y en la barra de contructor y depurar Principal hasta la resolución de Bar, puedes ver que PostBuildUp solo se llama una vez. Sin embargo, en el constructor de Bar, f1 es una instancia de Foo2 (una instancia "envuelta") mientras que f2 y f3 son instancias de Foo1 (sin envolver).

Me preguntaba si lo que quiero es posible y si estoy tomando el enfoque correcto. ¿Están mis problemas relacionados con el tiempo de vida y/o el UnityBuildStage para el que agregué el BuilderStrategy?

Gracias

+0

¿Se refiere a Unity Game Engine? –

+4

Creo que se está refiriendo a Unity como en el contenedor http://unity.codeplex.com/ – aqwert

Respuesta

2

que estás haciendo la estrategia de interceptación demasiado tarde en la estrategia de construcción. Lamentablemente, en este momento no tengo un motivo más detallado para por qué el código se comporta de esta manera dentro del ensamblaje ObjectBuilder.

suerte, voy a volver cuando tenga más tiempo para analizar la ObjectBuilder Unidad, pero para resolver su problema en el ínterin, acaba de cambiar su valor UnityBuildStage enumeración de postinicialización a Configuración o TypeMapping

Context.Strategies.AddNew<MyInterceptionStrategy>(UnityBuildStage.Setup); 

Mi código completo:

using System; 
using Microsoft.Practices.ObjectBuilder2; 
using Microsoft.Practices.Unity; 
using Microsoft.Practices.Unity.ObjectBuilder; 

namespace UnityInterceptors 
{ 
    class Program 
    { 
     public class MyInterception : UnityContainerExtension 
     { 
      protected override void Initialize() 
      { 
       Context.Strategies.AddNew<MyInterceptionStrategy>(UnityBuildStage.Setup); 
      } 
     } 
     public class MyInterceptionStrategy : BuilderStrategy 
     { 
      public override void PostBuildUp(IBuilderContext context) 
      { 
       if (!context.OriginalBuildKey.Type.IsInterface) 
       { 
        return; 
       } 

       context.Existing = new Foo2(); 
      } 
     } 

     public class Bar 
     { 
      public Bar(IFoo f1, IFoo f2, IFoo f3) 
      { 
       Console.WriteLine(f1.GetType().Name); 
       Console.WriteLine(f2.GetType().Name); 
       Console.WriteLine(f3.GetType().Name); 
      } 
     } 

     public interface IFoo 
     { 
     } 

     public class Foo1 : IFoo 
     { 
     } 

     public class Foo2 : IFoo 
     { 
     } 

     public static void Main() 
     { 
      UnityContainer container = new UnityContainer(); 
      container.AddNewExtension<MyInterception>(); 
      container.RegisterType(typeof(IFoo), typeof(Foo1), new PerResolveLifetimeManager()); 

      container.Resolve<Bar>(); 

      Console.ReadLine(); 
     } 
    } 
} 
  • También tenga en cuenta que estoy usando la biblioteca de Unity 2.0. Podría ser algún tipo de error que se ha resuelto.
Cuestiones relacionadas