Можно Castle.Windsor сделать автоматическое разрешение конкретных типов - PullRequest
6 голосов
/ 24 декабря 2009

Мы оцениваем контейнеры IoC для проектов C #, и Unity, и Castle.Windsor выделяются. Одна вещь, которая мне нравится в Unity (NInject и StructureMap также делают это), это то, что типы, для которых очевидно, как их создавать, не должны регистрироваться в контейнере IoC.

Есть ли способ сделать это в Castle.Windsor? Я честен с Каслом. Виндзор сказал, что он этого не делает? Есть ли конструктивная причина, чтобы сознательно не делать этого, или это упущение, или просто не считается важным или полезным?

Я знаю о container.Register(AllTypes... в Виндзоре, но это не совсем то же самое. Он не совсем автоматический и очень широкий.

Чтобы проиллюстрировать это, вот два теста NUnit, которые делают то же самое через Unity и Castle.Windsor. Замок. Виндзор один терпит неудачу. :

namespace SimpleIocDemo
{
    using NUnit.Framework;
    using Castle.Windsor;
    using Microsoft.Practices.Unity;

    public interface ISomeService
    {
        string DoSomething();
    }

    public class ServiceImplementation : ISomeService
    {
        public string DoSomething()
        {
            return "Hello";
        }
    }

    public class RootObject
    {
        public ISomeService SomeService { get; private set; }

        public RootObject(ISomeService service)
        {
            SomeService = service;
        }
    }

    [TestFixture]
    public class IocTests
    {
        [Test]
        public void UnityResolveTest()
        {
            UnityContainer container = new UnityContainer();
            container.RegisterType<ISomeService, ServiceImplementation>();
            // Root object needs no registration in Unity
            RootObject rootObject = container.Resolve<RootObject>();
            Assert.AreEqual("Hello", rootObject.SomeService.DoSomething());
        }

        [Test]
        public void WindsorResolveTest()
        {
            WindsorContainer container = new WindsorContainer();
            container.AddComponent<ISomeService, ServiceImplementation>();

            // fails with exception "Castle.MicroKernel.ComponentNotFoundException: 
            // No component for supporting the service SimpleIocDemo.RootObject was found"
            // I could add
            // container.AddComponent<RootObject>();
            // but that approach does not scale
            RootObject rootObject = container.Resolve<RootObject>();
            Assert.AreEqual("Hello", rootObject.SomeService.DoSomething());
        }
    }
}

1 Ответ

6 голосов
/ 24 декабря 2009

Виндзор не поддерживает это из коробки, и это осознанное решение. См. этот ответ для более подробной информации.

Однако, более поздние версии могут быть действительно легко расширены для поддержки этого сценария путем ленивой регистрации незарегистрированных компонентов по мере их запроса. Вам нужно будет реализовать интерфейс ILazyComponentLoader, который займет 5 строк кода. См. здесь для примера.

Несмотря на то, что мое предложение в 2018 году такое же, как и в 2009 году - не делайте этого, если только в очень определенных сценариях, когда у вас есть очень хорошая причина, чтобы выбрать это подход над альтернативами

...