可以Castle.Windsor自动解决具体类型

时间:2009-12-23 22:06:07

标签: .net inversion-of-control castle-windsor unity-container ioc-container

我们正在为C#项目评估IoC容器,Unity和Castle.Windsor都很突出。我喜欢Unity的一件事(NInject和StructureMap也这样做)是明显如何构造它们的类型不必在IoC容器中注册。

有没有办法在Castle.Windsor中这样做?我对Castle很公平。温莎要说它不这样做吗?有没有设计理由故意不这样做,或者是疏忽,还是只是没有被视为重要或有用?

我知道温莎的container.Register(AllTypes...,但这不是一回事。它不是完全自动化的,而且非常广泛。

为了说明这一点,这里有两个NUnit测试通过Unity和Castle.Windsor做同样的事情。 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 个答案:

答案 0 :(得分:6)

Windsor并不支持开箱即用,这是一个慎重的决定。有关详细信息,请参阅this answer

然而,通过懒惰地注册未注册的组件,可以非常容易地扩展更高版本以支持这种情况,因为它们是被请求的。 您必须实现ILazyComponentLoader接口,这将占用5行代码。有关示例,请参阅here

尽管我在2018年提出的建议与2009年的相同 - 除非在非常特定情况下你有非常良好理由,否则不要这样做选择这种方法而非替代方案