2008-12-24 4 views
6

Je ne sais pas si c'est une question trop spécifique, si cela est possible, mais je dois porter une application qui utilise Castle Windsor pour Unity afin qu'il n'y ait pas de dépendance aux bibliothèques non-approuvées par microsoft. Je sais que je sais mais qu'allez-vous faire.Castle Windsor à Unity - pouvez-vous configurer automatiquement dans Unity de la même manière que vous le pouvez en CW?

Quoi qu'il en soit, je suis parvenu, mais je ne suis pas content de ce que j'ai. À Windsor, j'ai eu ceci:

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

que j'ai converti à cette unité dans

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

Comme vous pouvez le voir, je suis d'avoir à enregistrer chaque chose plutôt que d'être en mesure d'utiliser une sorte de l'auto-configuration. Ma question est la suivante: y a-t-il une meilleure façon de faire cela dans l'unité?

Merci,

Adam.

+0

une idée serait d'extraire le code utilisé pour enregistrer() dans la source de CastleWindsor, et faire une méthode d'extension hors du conteneur unité. – eduncan911

+0

Si vous déménagez à Unity, veuillez accepter mes condoléances. Vous êtes prêt pour un monde de douleur, surtout si vous avez beaucoup utilisé Windsor, et non trivialement –

Répondre

0

Cool. Cette fonctionnalité n'est pas encore dans l'unité mais si vous vous sentiez un peu ambitieux, vous pouvez configurer votre propre enregistrement basé sur les conventions. Trouvé ci-dessous est un snipped qui fonctionne pour l'exécution de l'assemblage et des interfaces. Bonne chance.

P.S. Cela ressemble à un grand bidouillage, je continuerais probablement à enregistrer tous les types à la main.

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

Pas tellement d'un hack, comme la source de CastleWindsor fait quelque chose de similaire (que ce soit, beaucoup plus élégamment). Une meilleure idée pour lui serait de déchirer le code utilisé pour Register(), et de faire une méthode d'extension hors du conteneur Unity/ – eduncan911

+0

Juste pour que je sois clair que vous voulez le retirer de Windsor puis l'appliquer à Unity? Bien sûr, pourquoi pas! Ya ... l'élégance? Peut-être le prochain projet;). – smaclell

-1

AFAIK il n'y a aucun moyen de le faire dans Unity. L'unité est tout simplement beaucoup moins mature et pire conteneur architectural que Windsor, et à la suite de cela beaucoup de choses sont plus difficiles/impossibles avec elle.

5

Check this out:

 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

auto-promotion éhontée! J'aime ça. – smaclell

+0

Aussi très joli code source. Si je dois utiliser Unity, je l'inclurai définitivement;). – smaclell

0

Je viens de tombé sur cette question à la recherche d'informations sur l'inscription fondée sur les conventions-Windsor et je pensais que je laisse tout cela est une question assez ancienne réponse pour les autres qui peut-être chercher ce genre de capacités dans Unity.

L'année dernière, j'ai écrit une extension d'enregistrement basée sur la convention pour Unity que vous pouvez lire à propos de here. Le téléchargement réel est disponible sur google code here. L'utilisation de base est:

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

Il y a aussi un ClosingTypeConvention pour les types génériques ouverts auto-enregistrement:

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

Unité 3 prend désormais en charge l'enregistrement par convention de la boîte.

Voici enregistrerait et carte toutes vos mises en œuvre concrètes à une interface qui suit la convention: IFoo -> Foo

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

Par ailleurs, vous n'avez pas besoin d'enregistrer les classes de type béton (tout comme le cas avec vos classes XXXPresenter) si elles ne correspondent pas à un type différent ... Unity le construira automatiquement si une classe dépend d'un type concret.Il y a beaucoup plus à faire avec les conventions, comme le filtrage des assemblages ou des types à utiliser, ou comment le mappage est effectué, mais je vous suggère de regarder les exemples dans MSDN, car ils couvrent plusieurs d'entre eux:

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

Questions connexes