2008-12-24 3 views
6

Я не знаю, является ли это слишком конкретным вопросом, если это возможно, но мне нужно перенести приложение, которое использует Castle Windsor для Unity, чтобы не было уверенности в том, что библиотеки, не одобренные для Microsoft. Я знаю, что знаю, но что ты собираешься делать.Castle Windsor to Unity - можете ли вы автоматически настроить в Unity так же, как вы можете в CW?

Во всяком случае, я справился с этим, но я не доволен тем, что у меня есть. В Виндзоре Я это:

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

который я преобразован в это в единстве

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

Как вы можете видеть, у меня зарегистрировать каждую вещь, а не быть в состоянии использовать какой-то автоконфигурации. Поэтому мой вопрос: есть ли лучший способ сделать это в единстве?

Thanks,

Adam.

+0

идея будет выдирать код, используемый для регистра() в источнике CastleWindsor, и сделать метод расширения от контейнера Unity. – eduncan911

+0

Если вы переезжаете в Единство, примите мои соболезнования. Вы готовы к миру боли, особенно если вы широко использовали Виндзор и нетривиально. –

ответ

0

Прохладный. Эта особенность еще не в единстве, но если вы почувствовали себя немного амбициозным, вы можете настроить собственную регистрацию на основе конвенций. Ниже приведен фрагмент, который работает для исполняющей сборки и интерфейсов. Удачи.

P.S. Это похоже на большой взлом, я, вероятно, продолжу просто регистрировать все типы вручную.

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

Не так много взлома, так как источник CastleWindsor делает что-то похожее (пусть и более элегантно). Лучшей идеей для него было бы вырвать код, используемый для Register(), и сделать метод расширения из контейнера Unity/ – eduncan911

+0

. Просто я понял, что вы имеете в виду вывести его из Виндзора, а затем применить его к Unity? Конечно, почему бы и нет! Я ... элегантность? Возможно, следующий проект;). – smaclell

-1

AFAIK В Unity нет возможности сделать это. Единство - это намного менее зрелый и худший, чем в Виндзоре, контейнер, и в результате этого с ним многое и сложнее.

5

Проверить this из:

 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

бесстыдная самооценка! Я люблю это. – smaclell

+0

Также очень хороший исходный код. Если я должен использовать Unity, я обязательно включу его;). – smaclell

0

Я просто наткнулся на этот вопрос ищет информацию о регистрации конвенции на основе для Виндзоре и в то время как это довольно старый вопрос, я думал, что оставить ответ для тех, кто возможно, ищет такие возможности в Unity.

В прошлом году я написал условное регистрационное расширение для Unity, которое вы можете прочитать о here. Фактическая загрузка доступна по коду Google here. Основное использование является:

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

Существует также ClosingTypeConvention для автоматической регистрации открытых родовых типов:

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

Unity 3 теперь поддерживает регистрацию по соглашению из коробки.

Следующая зарегистрирует и отображать все ваши конкретные реализации в интерфейс, который соответствует соглашению: IFoo -> Foo

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

Кстати, вам не нужно регистрироваться конкретные классы типов (как случай с вашими классами XXXPresenter), если они не сопоставляются с другим типом ... Unity автоматически создаст его, если класс зависит от конкретного типа.

Существует гораздо больше возможностей для соглашений, таких как фильтрация, какие сборки или типы использовать или как выполняется сопоставление, но я бы предложил вам ознакомиться с примерами в MSDN, поскольку они охватывают несколько из них:

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