2008-12-24 19 views
6

Nie wiem, czy jest to zbyt szczegółowe pytanie, jeśli jest to możliwe, ale muszę podłączyć aplikację, która używa Castle Windsor do Unity, aby nie polegać na bibliotekach zatwierdzonych przez inną firmę niż microsoft. Wiem, że wiem, ale co masz zamiar zrobić.Castle Windsor to Unity - czy możesz automatycznie skonfigurować w Unity w taki sam sposób, jak w CW?

W każdym razie udało mi się, ale nie jestem zadowolony z tego, co mam. W Windsor miałem to:

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

który ja przekształca się to w jedności

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

Jak widać mam się rejestrować każdą rzecz, zamiast być w stanie wykorzystać jakąś automatycznej konfiguracji. Moje pytanie brzmi: czy istnieje lepszy sposób robienia tego w jedności?

Dzięki,

Adam.

+0

pomysł byłoby wyrwać kod używany do rejestru() w źródle CastleWindsor, a uczynić metodę rozszerzenia off kontenera Unity. – eduncan911

+0

Jeśli przeprowadzasz się do Unity, przyjmij moje kondolencje. Masz ochotę na świat pełen bólu, zwłaszcza jeśli używałeś Windsora szeroko i nietrywialnie. –

Odpowiedz

0

Cool. Ta funkcja nie jest jeszcze w jedności, ale jeśli czujesz się nieco ambitny, możesz skonfigurować własną rejestrację opartą na konwencjach. Poniżej znajduje się wycinek, który działa dla zespołu wykonawczego i interfejsów. Powodzenia.

P.S. To wydaje się być wielkim hackerem, prawdopodobnie kontynuowałbym rejestrowanie wszystkich typów ręcznie.

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

Nie tyle o hackach, ile o źródle CastleWindsor robi coś podobnego (czy to o wiele bardziej elegancko). Lepszym pomysłem dla niego byłoby wyrwanie kodu użytego w Register() i wykonanie metody przedłużenia z kontenera Unity/ – eduncan911

+0

. Czyli mam na myśli wyjęcie go z Windsoru i zastosowanie go do Unity? Jasne, czemu nie! Tak ... elegancja? Może następny projekt;). – smaclell

-1

AFAIK nie ma sposobu, aby to zrobić w Jedności. Jedność jest po prostu znacznie mniej dojrzałym i gorzej zaprojektowanym pojemnikiem niż Windsor, a w wyniku tego wiele rzeczy jest z nim trudniejszych/niemożliwych.

5

Sprawdź this się:

 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

bezwstydna autopromocja! Kocham to. – smaclell

+0

Również bardzo ładny kod źródłowy. Jeśli będę musiał korzystać z Jedności, zdecydowanie go uwzględnię;). – smaclell

0

Właśnie natknęliśmy się na to pytanie szuka informacji na temat rejestracji konwencji opartej na Windsor, a jednocześnie jest to dość stary pytanie pomyślałem, że zostawić odpowiedź dla innych, którzy może szukają tego rodzaju możliwości w Unity.

W ubiegłym roku napisałem konwencyjne rozszerzenie rejestracji dla Unity, które można przeczytać o here. Rzeczywiste pobieranie jest dostępne pod kodem google here. Podstawowe użycie jest:

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

Istnieje również ClosingTypeConvention dla auto-rejestracji otwartych typów generycznych:

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

Unity 3 obsługuje teraz rejestracji przez konwencję po wyjęciu z pudełka.

Poniższy by zarejestrować i odwzorować wszystkie swoje konkretne implementacje do interfejsu, który następuje po konwencji: IFoo -> Foo

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

nawiasem mówiąc, nie trzeba się rejestrować klas typu betonu (jak ma to miejsce w przypadku klas XXXPresenter), jeśli nie mapują one do innego typu ... Unity automatycznie je zbuduje, jeśli klasa będzie zależeć od konkretnego typu.

Z konwencjami można zrobić o wiele więcej, np. Filtrowanie, które zespoły lub typy są używane, lub sposób ich mapowania, ale proponuję przejrzeć przykłady w witrynie MSDN, ponieważ obejmują one kilka z nich:

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