可以Castle.Windsor做的具体类型自动解析具体、类型、Castle、Windsor

2023-09-04 09:28:43 作者:遇念

我们正在评估的IoC容器C#项目,都团结Castle.Windsor都站出来。我喜欢团结(NInject和StructureMap也是这样做)的一个事情是,各类地方是显而易见的如何构建他们不必与IoC容器注册。

有没有办法做到这一点的Castle.Windsor?我是不是公平的Castle.Windsor地说,它不这样做呢?是否有一个设计的理由故意不这样做,或者是一个疏忽,或者只是不被视为重要的或有用吗?

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

要说明这一点,这里有两个NUnit的测试做通过团结和Castle.Windsor同样的事情。该Castle.Windsor一个出现故障。

 命名空间SimpleIocDemo
{
    使用NUnit.Framework;
    使用Castle.Windsor;
    使用Microsoft.P​​ractices.Unity;

    公共接口ISomeService
    {
        字符串DoSomething的();
    }

    公共类ServiceImplementation:ISomeService
    {
        公共字符串DoSomething的()
        {
            返回你好;
        }
    }

    公共类RootObject
    {
        公共ISomeService SomeService {获得;私定; }

        公共RootObject(ISomeService服务)
        {
            SomeService =服务;
        }
    }

    [的TestFixture]
    公共类IocTests
    {
        [测试]
        公共无效UnityResolveTest()
        {
            UnityContainer集装箱=新UnityContainer();
            container.RegisterType&所述; ISomeService,ServiceImplementation>();
            //根对象需要在Unity没有注册
            RootObject rootObject = container.Resolve&其中; RootObject>();
            Assert.AreEqual(你好,rootObject.SomeService.DoSomething());
        }

        [测试]
        公共无效WindsorResolveTest()
        {
            WindsorContainer集装箱=新WindsorContainer();
            container.AddComponent&所述; ISomeService,ServiceImplementation>();

            //失败,除Castle.MicroKernel.ComponentNotFoundException:
            //没有组件配套服务SimpleIocDemo.RootObject发现
            //我可以添加
            // container.AddComponent&其中; RootObject>();
            //但是这种方法没有规模
            RootObject rootObject = container.Resolve&其中; RootObject>();
            Assert.AreEqual(你好,rootObject.SomeService.DoSomething());
        }
    }
}
 
hashcode Castle Windsor 解析不到我的类型 CSDN问答频道

解决方案

温不支持此开箱即用,这是一个深思熟虑的决定。

不过,主干版本可以真正轻松地延长懒洋洋地注册非注册的组件,以支持此方案,因为它们要求。 你必须实施 ILazyComponentLoader 接口,这将需要像5系code。请参阅这里一个例子。

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

解决方案

Windsor does not support this out of the box, and this is a deliberate decision.

However, the trunk version 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.