企业库Unity与其他IoC容器的比较

137

使用企业库Unity相对于其他IoC容器(Windsor,Spring.Net,Autofac等)的利弊是什么?


9
这些类型的问题通常会被关闭。观点很重要。是否有一个适合它们的地方? - Jeson Martajaya
1
@JesonMartajaya,我想赞同你的评论,关闭问题却没有提供替代方案真的很烦人。 - Mohammed Noureldin
8个回答

237

我正在为一个用户组准备演示文稿。因此,我刚刚查看了一堆内容。包括:AutoFac、MEF、Ninject、Spring.Net、StructureMap、Unity和Windsor。

我想展示90%的情况(构造函数注入,这主要是人们使用IOC的原因)。 您可以在此处查看解决方案(VS2008)

因此,有一些关键的区别:

  • 初始化
  • 对象检索

它们每个都有其他功能(一些具有AOP和更好的小工具,但通常我只想让IOC为我创建和检索对象)

注意:使用CommonServiceLocator可以消除不同库之间对象检索的差异:http://www.codeplex.com/CommonServiceLocator

这就留下了初始化,有两种方式:通过代码或通过XML配置(app.config/web.config/custom.config)。有些支持两者,有些只支持其中一种。我应该指出:有些使用属性来帮助IoC。

所以这里是我对差异的评估:

Ninject

仅支持代码初始化(带属性)。我希望您喜欢lambda表达式。初始化代码如下:

 IKernel kernel = new StandardKernel(
                new InlineModule(
                    x => x.Bind<ICustomerRepository>().To<CustomerRepository>(),
                    x => x.Bind<ICustomerService>().To<CustomerService>(),
                    x => x.Bind<Form1>().ToSelf()
                    ));

StructureMap

StructureMap可以使用初始化代码、XML或属性进行配置。v2.5版本也非常适合使用Lambda表达式。总的来说,这是我最喜欢的之一。关于StructureMap如何使用属性有一些非常有趣的想法。

ObjectFactory.Initialize(x =>
{
    x.UseDefaultStructureMapConfigFile = false;
    x.ForRequestedType<ICustomerRepository>()
        .TheDefaultIsConcreteType<CustomerRepository>()
        .CacheBy(InstanceScope.Singleton);

    x.ForRequestedType<ICustomerService>()
        .TheDefaultIsConcreteType<CustomerService>()
        .CacheBy(InstanceScope.Singleton);

    x.ForConcreteType<Form1>();
 });

Unity

这是一个不错的库,但XML配置有点麻烦。适用于微软或高速公路店的优秀库。 代码初始化很容易:

 container.RegisterType<ICustomerRepository, CustomerRepository>()
          .RegisterType<ICustomerService, CustomerService>();

Spring.NET

据我所知,Spring.NET 仅支持 XML。但是在功能方面,Spring.NET 可以实现 IoC 的所有功能。但由于单元化的唯一方式是通过 XML,因此它通常被 .net 店铺所避免。尽管如此,许多 .net/Java 店铺使用 Spring.NET,因为 .net 版本的 Spring.NET 与 Java Spring 项目非常相似。

注意:随着 Spring.NET CodeConfig 的引入,现在可以在代码中进行配置。

Windsor

支持 XML 和代码。与 Spring.NET 类似,Windsor 可以实现您想要的任何功能。 Windsor 可能是最受欢迎的 IoC 容器之一。

IWindsorContainer container = new WindsorContainer();
container.AddComponentWithLifestyle<ICustomerRepository, CustomerRepository>("CustomerRepository", LifestyleType.Singleton);
container.AddComponentWithLifestyle<ICustomerService, CustomerService>("CustomerService",LifestyleType.Singleton);
container.AddComponent<Form1>("Form1");

Autofac

使用 v1.2 版本可以同时使用 XML 和代码。这是一个不错的、简单的 IoC 库。它似乎只做基础操作,没有太多麻烦。支持带有本地范围组件的嵌套容器和良好定义的生命周期管理。

以下是初始化方法:

var builder = new ContainerBuilder();
builder.Register<CustomerRepository>()
        .As<ICustomerRepository>()
        .ContainerScoped();
builder.Register<CustomerService>()
        .As<ICustomerService>()
        .ContainerScoped();
builder.Register<Form1>();

如果我今天必须做出选择:我可能会选择StructureMap。它对C# 3.0语言特性有最好的支持,并且初始化时最为灵活。

注意:Chris Brandsma将他原来的回答转化成了一篇博客文章


1
仅使用Xml配置,使其更难配置。基本上,我只看到想要使用Spring.Net的人是前Java开发人员。 - Chris Brandsma
2
嗨,尼古拉斯:关于C# 3的支持,Autofac已经做到了一切。 :)对于初始化,我希望能够轻松支持单例/非单例和每个会话的初始化。最后,我希望有简单的方法来按自定义名称引用。(这在StructureMap中是一个烦人的问题)。现在比我最初写这篇文章时更喜欢的最终功能是AutoMocking。我并不总是使用它,但拥有它确实非常好。 - Chris Brandsma
你提到了MEF,我使用MEF来传递我的IRepository实现对象,并且发现它运行得非常好。你对MEF有什么想法? - terjetyl
Unity支持xml和代码配置。它是一个非常成熟和灵活的容器。 - Woland
@Chris Spring的代码配置可用。http://springframework.net/codeconfig/ - Beachwalker
显示剩余4条评论

7
据我所见,它们基本相同,除了一些实现细节。Unity相对于竞争对手的最大优势是由Microsoft提供,有很多公司担心开源软件。但Unity的缺点之一是它比较新,可能存在已经被老牌玩家解决的漏洞。话虽如此,您可能想要查看这个

4

虽然这是一个旧帖子,但当我输入“unity vs spring.net”时,这是谷歌显示给我的第一件事......

现在 Spring 已经可以使用 CodeConfig 了,如果您不喜欢 XML 配置的话。

http://www.springframework.net/codeconfig/doc-latest/reference/html/

此外,Spring 不仅仅是一个 DI 容器,在文档中的“模块”部分,DI 容器是它所做的众多工作的基础。


3

如果我理解错误,请纠正我,但我认为Autofac本身支持XML配置,具体可以参考这个链接:Autofac XML Configuration


2
Spring有一个特性,它可以根据参数名称或位置将参数注入到构造函数或属性中。如果参数或属性是简单类型(例如整数、布尔值),这非常有用。请参见此处的示例。我认为这并不能弥补Spring无法在代码中进行配置的缺陷。
Windsor也可以做到这一点,并且可以在代码而不是配置中实现。(如果我说错了,请纠正我,我只是根据我听到的来说)。
我想知道Unity是否能做到这一点。

2

需要注意的一点是:据Ninject网站介绍,它是唯一支持上下文依赖注入的IoC容器。但是,由于我没有其他IoC容器的经验,无法确定是否属实。


如果Ninject中的“上下文依赖注入”就是这样,那么...嗯,没有什么特别的。至少在Unity、AutoFac和Windsor中通过各种方式得到支持。 - user2864740

1
只是想补充一下,我尝试过StructureMap和Unity。我发现StructureMap文档质量很差/误导性强,配置起来很麻烦,使用起来也很笨重。同样的,它似乎不支持在解析时覆盖构造函数参数的情况,这对我来说是一个关键的使用点。所以我放弃了它,转而选择了Unity,并在大约20分钟内让它做到了我想要的事情。

1
我个人使用Unity,但只是因为它来自微软。我对这个决定感到遗憾的原因是:它最大的问题是有一个“bug”,导致它不断抛出异常。在调试时可以忽略这些异常,但如果你遇到了它,它会极大地减慢你的应用程序,因为抛出异常是一项昂贵的操作。例如,我目前正在我的代码中的一个位置“修复”这个异常,其中Unity的异常将额外增加4秒的页面渲染时间。有关更多详细信息和解决方法,请参见:Unity能否不一直抛出SynchronizationLockException?

谢谢你的提醒!根据你所提到的问题中的这个答案,该漏洞现在已经得到解决。 - Sam
为什么Unity会抛出异常?通常,异常是一个“关键错误”(例如无法解决的依赖项),而不是应该被压制的东西。 - user2864740
请问,这个“bug”已经解决了还是你找到了避免它的方法?我现在正在选择C#.NET框架,很想知道Unity是否仍然需要花费时间... - Jog Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接