Castle Windsor to Unity - можете ли вы автоматически настроить Unity так же, как в CW? - PullRequest
6 голосов
/ 24 декабря 2008

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

В любом случае, мне это удалось, но я не доволен тем, что у меня есть. В Виндзоре у меня было это:

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>();

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

Спасибо

Адам.

Ответы [ 5 ]

5 голосов
/ 08 октября 2009

Проверьте это 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();
2 голосов
/ 06 июня 2013

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

0 голосов
/ 03 марта 2010

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

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

  _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();
0 голосов
/ 30 декабря 2008

AFAIK нет способа сделать это в Unity. Unity просто гораздо менее зрелый и худший архитектурный контейнер, чем Windsor, и в результате этого многие вещи становятся сложнее / невозможнее.

0 голосов
/ 25 декабря 2008

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

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; }
        }        
    }
}
...