我们正在为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());
}
}
}
答案 0 :(得分:6)
Windsor并不支持开箱即用,这是一个慎重的决定。有关详细信息,请参阅this answer。
然而,通过懒惰地注册未注册的组件,可以非常容易地扩展更高版本以支持这种情况,因为它们是被请求的。
您必须实现ILazyComponentLoader
接口,这将占用5行代码。有关示例,请参阅here。
尽管我在2018年提出的建议与2009年的相同 - 除非在非常特定情况下你有非常良好理由,否则不要这样做选择这种方法而非替代方案