2008-12-24 15 views
6

No sé si esta es una pregunta demasiado específica, si eso es posible, pero tengo que portar una aplicación que usa Castle Windsor a Unity para que no haya una dependencia en bibliotecas no aprobadas por Microsoft. Sé que lo sé, pero ¿qué vas a hacer?Castle Windsor to Unity: ¿puedes autoconfigurar en Unity de la misma manera que en CW?

De todos modos lo he logrado, pero no estoy contento con lo que tengo. En Windsor Tenía esta:

Register(
      AllTypes.Of(typeof(AbstractPresenter<>)).FromAssemblyNamed("Links.Mvp"), 
      AllTypes.Of(typeof(IView)).FromAssemblyNamed("Links.WinForms").WithService.FromInterface()); 

la que me he convertido a esta en la unidad

RegisterType<IMainView, MainView>(); 
     RegisterType<IConfigureLinkView, ConfigureLinkView>(); 
     RegisterType<IConfigureSourceView, ConfigureSourceView>(); 
     RegisterType<IConfigureSinkView, ConfigureSinkView>(); 
     RegisterType<MainPresenter, MainPresenter>(); 
     RegisterType<ConfigureLinkPresenter, ConfigureLinkPresenter>(); 
     RegisterType<ConfigureSourcePresenter, ConfigureSourcePresenter>(); 
     RegisterType<ConfigureSinkPresenter, ConfigureSinkPresenter>(); 

Como se puede ver que estoy tengan que registrarse en cada cosa en lugar de ser capaz de utilizar algún tipo de la autoconfiguración Entonces mi pregunta es: ¿hay una forma mejor de hacer esto en unidad?

Gracias,

Adam.

+0

una idea sería arrancar el código utilizado para el registro() en el origen de CastleWindsor, y crea un método de extensión fuera del contenedor de la unidad. – eduncan911

+0

Si se muda a Unity, acepte mis condolencias. Estás dispuesto a un mundo de dolor, especialmente si has usado ampliamente Windsor, y no trivialmente –

Respuesta

0

Cool. Esta característica aún no está en la unidad, pero si te sientes un poco ambicioso, puedes configurar tu propio registro basado en la convención. A continuación, se encuentra un recorte que funciona para el ensamblaje de ejecución y las interfaces. Buena suerte.

P.S. Esto parece un gran truco, probablemente continuaría registrando todos los tipos a mano.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Reflection; 

namespace Forum 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // get your assemblies and types you can register 
      Assembly a = Assembly.GetExecutingAssembly(); 
      var types = a.GetTypes();    
      var bindTo = from t in types 
         where t.IsAbstract || t.IsInterface 
         select t; 

      // apply your conventions to filter our types to be registered 
      var interfacePairs = from t in bindTo.Where(x => x.IsInterface) 
           let match = types.FirstOrDefault(x => x.Name ==  t.Name.Substring(1)) 
           where match != null 
           select new Pair { To = t, From = match }; 
      var abstractPairs = new Pair[] {}; 


      // setup the generic form of the method to register the types 
      var thisType = typeof(Program); 
      var bindings = BindingFlags.Static | BindingFlags.Public; 
      MethodInfo genericMethod = thisType.GetMethod("RegisterType", bindings);    

      // register all your types by executing the 
      // specialized generic form of the method 
      foreach (var t in interfacePairs.Concat(abstractPairs)) 
      { 
       Type[] genericArguments = new Type[] { t.To, t.From }; 
       MethodInfo method = genericMethod.MakeGenericMethod(genericArguments); 
       method.Invoke(null, new object [] {}); 
      } 

      Console.ReadKey(); 
     } 

     public static void RegisterType<To, From>() 
     { 
      Console.WriteLine("Register { To: {0} From: {1} }", typeof(To), typeof(From)); 
     } 

     // Test classes that should be picked up 
     interface ITest { } 
     class Test : ITest { } 

     class Pair 
     { 
      public Type To { get; set; } 
      public Type From { get; set; } 
     }   
    } 
} 
+1

No tanto pirateo, ya que la fuente de CastleWindsor hace algo similar (ya sea, mucho más elegante). Una mejor idea para él sería arrancar el código usado para Register(), y hacer un método de extensión fuera del contenedor de Unity/ – eduncan911

+0

. ¿Así que estoy seguro de que quiere decir sacarlo de Windsor y luego aplicarlo a Unity? ¡Seguro Por qué no! Ya ... ¿elegancia? Tal vez el próximo proyecto;) – smaclell

-1

AFAIK no hay manera de hacerlo en Unity. Unity es simplemente un contenedor mucho menos maduro y peor diseñado que Windsor, y como resultado de eso, muchas cosas son más difíciles/imposibles con él.

5

Comprobar this a cabo:

 var container = new UnityContainer(); 

     container 
      .ConfigureAutoRegistration() 
      .LoadAssemblyFrom("Plugin.dll") 
      .IncludeAllLoadedAssemblies() 
      .ExcludeSystemAssemblies() 
      .ExcludeAssemblies(a => a.GetName().FullName.Contains("Test")) 
      .Include(If.Implements<ILogger>, Then.Register().UsingPerCallMode()) 
      .Include(If.ImplementsITypeName, Then.Register().WithTypeName()) 
      .Include(If.Implements<ICustomerRepository>, Then.Register().WithName("Sample")) 
      .Include(If.Implements<IOrderRepository>, 
        Then.Register().AsSingleInterfaceOfType().UsingPerCallMode()) 
      .Include(If.DecoratedWith<LoggerAttribute>, 
        Then.Register() 
          .AsInterface<IDisposable>() 
          .WithTypeName() 
          .UsingLifetime<MyLifetimeManager>()) 
      .Exclude(t => t.Name.Contains("Trace")) 
      .ApplyAutoRegistration(); 
+0

desvergonzada auto promoción! Lo amo. – smaclell

+0

También es un código fuente muy bueno. Si tengo que usar Unity, definitivamente lo incluiré;). – smaclell

0

simplemente me encontré con esta pregunta en busca de información sobre el registro basado en la convención de Windsor y si bien esto es una pregunta bastante antiguo que pensé en dejar una respuesta para otros que puede estar buscando este tipo de capacidades en Unity.

El año pasado escribí una extensión de registro basada en convenciones para Unity que puede leer acerca de here. La descarga real está disponible en el código de google here. El uso básico es:

_container 
     .Using<IConventionExtension>() 
     .Configure(x => 
      { 
       x.Conventions.Add<InterfaceImplementionNameMatchConvention>(); 
       x.Assemblies.Add(Assembly.GetExecutingAssembly()); 
      }) 
     .Register(); 

También hay un ClosingTypeConvention de tipos genéricos abiertos de auto-registro:

_container 
       .Using<IConventionExtension>() 
       .Configure(x => 
        { 
         x.Conventions.Add(new ClosingTypeConvention(typeof (IRepository<>))); 
         x.Assemblies.Add(Assembly.GetExecutingAssembly()); 
        }) 
       .Register(); 
2

Unidad 3 ahora soporta el registro por convención fuera de la caja.

El siguiente sería registrar y mapear todas sus implementaciones concretas a una interfaz que sigue la convención: IFoo -> Foo

var container = new UnityContainer(); 
container.RegisterTypes(
    AllClasses.FromLoadedAssemblies(), 
    WithMappings.MatchingInterface, 
    WithName.Default); 

Por cierto, no es necesario registrar el tipo clases concretas (como es el caso con sus clases de XXXPresenter) si no se asignan a un tipo diferente ... Unity lo creará automáticamente si una clase depende de un tipo concreto.

Puede hacer mucho más con las convenciones, como filtrar qué ensamblajes o tipos usar, o cómo se realiza la asignación, pero le sugiero que mire los ejemplos en MSDN, ya que cubren varios de estos:

http://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx#sec23