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

发布于 2024-08-16 10:30:53 字数 2154 浏览 5 评论 0原文

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

在 Castle.Windsor 有办法做到这一点吗?我公平地说 Castle.Windsor 不会这样做吗?是否有设计原因故意不这样做,或者这是一个疏忽,或者只是不被视为重要或有用?

我知道 Windsor 中有 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());
        }
    }
}

We are evaluating IoC containers for C# projects, and both Unity and Castle.Windsor are standing out. One thing that I like about Unity (NInject and StructureMap also do this) is that types where it is obvious how to construct them do not have to be registered with the IoC Container.

Is there way to do this in Castle.Windsor? Am I being fair to Castle.Windsor to say that it does not do this? Is there a design reason to deliberately not do this, or is it an oversight, or just not seen as important or useful?

I am aware of container.Register(AllTypes... in Windsor but that's not quite the same thing. It's not entirely automatic, and it's very broad.

To illustrate the point, here are two NUnit tests doing the same thing via Unity and Castle.Windsor. The Castle.Windsor one fails. :

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疯了 2024-08-23 10:30:53

Windsor 不支持这种开箱即用的做法,这是一个经过深思熟虑的决定。有关更多详细信息,请参阅此答案

但是,通过根据请求延迟注册未注册的组件,可以非常轻松地扩展更高版本以支持这种情况。
您必须实现 ILazyComponentLoader 接口,这将占用大约 5 行代码。请参阅此处了解例子。

尽管我在 2018 年的建议与 2009 年的建议相同 - 不要这样做,除非在非常特定场景中,您有非常充分的理由选择此方法超过替代品

Windsor does not support this out of the box, and this is a deliberate decision. See this answer for more details.

However, the later versions can be really easily extended to support this scenario by lazily registering non-registered components, as they are requested.
You'll have to implement ILazyComponentLoader interface, which will take up like 5 lines of code. See here for an example.

Despite that my suggestion in 2018 is the same as it was in 2009 - don't do it unless in very specific scenarios where you have a very good reason to choose this approach over alternatives

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文