企业库Unity与其他IoC容器

时间:2009-01-04 21:00:31

标签: c# .net inversion-of-control unity-container enterprise-library

使用Enterprise Library Unity与其他IoC容器(Windsor,Spring.Net,Autofac ..)的优缺点是什么?

8 个答案:

答案 0 :(得分:232)

我正在为用户组准备演示文稿。因此,我刚刚经历了一堆。即:AutoFac,MEF,Ninject,Spring.Net,StructureMap,Unity和Windsor。

我想展示90%的情况(构造函数注入,主要是人们使用IOC的情况)。 You can check out the solution here (VS2008)

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

  • 初始化
  • 对象检索

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

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

这使我们初始化,这有两种方式:通过代码或通过XML配置(app.config / web.config / custom.config)。有些支持,有些只支持一种。我应该注意:有些人使用属性来帮助IoC。

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

Ninject

仅代码初始化(带属性)。我希望你喜欢lambdas。初始化代码如下所示:

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

StructureMap

初始化代码或XML或属性。 v2.5也非常lambdayy。总而言之,这是我的最爱之一。关于StructureMap如何使用Attributes的一些非常有趣的想法。

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。不错的库,但XML配置是一个痛苦的屁股。适用于Microsoft或高速公路商店的优秀图书馆。 代码初始化很简单:

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

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

可以混合使用XML和代码(使用v1.2)。不错的简单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将原来的答案改为blog post

答案 1 :(得分:7)

据我所知,它们几乎相同,除了一些实现细节之外。 Unity在竞争中的最大优势在于它是由微软提供的,有很多公司都害怕OSS。

一个缺点是它相当新,所以它可能有老玩家已经解决的错误。

话虽如此,您可能想要check this out

答案 2 :(得分:4)

旧线程,但因为这是Google在我输入unity vs spring.net时向我展示的第一件事......

如果您不喜欢XML配置,Spring现在会执行CodeConfig

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

另外,Spring不仅仅是一个DI容器,如果你看一下docs中的“Modules”部分,DI容器就是它所做的大量事情的基础。

答案 3 :(得分:3)

如果我弄错了,请纠正我,但我认为Autofac本身支持此链接中列出的XML配置:Autofac XML Configuration

答案 4 :(得分:2)

Spring有一个功能,它可以根据参数名称或位置为构造函数或属性注入参数。如果参数或属性是简单类型(例如整数,布尔值),这非常有用。见the example here。我不认为这真的弥补了Spring无法在代码中进行配置。

Windsor也可以这样做,并且可以在代码中进行配置。 (纠正我,如果我错了,我只是通过我在这里听到的内容)。

我想知道Unity是否可以做到这一点。

答案 5 :(得分:2)

有一点需要注意:Ninject是唯一支持上下文依赖注入的IoC容器(根据其网站)。但是,因为我没有其他IoC容器的经验,所以我不知道这是否成立。

答案 6 :(得分:1)

为了加上我的2美分,我尝试了StructureMap和Unity。我发现StructureMap很难/错误地记录,配置的屁股很痛苦,而且使用起来很笨拙。同样,它似乎不支持解析时的构造函数参数覆盖等场景,这对我来说是一个关键的使用点。所以我放弃了它,然后和Unity一起去了,并且在大约20分钟内完成了我想做的事。

答案 7 :(得分:1)

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

Can Unity be made to not throw SynchronizationLockException all the time?