使用Autofac会有什么优缺点

时间:2009-04-14 04:30:11

标签: inversion-of-control autofac

我读过关于Autofac的消息,它很快。我已经看到了涉及的编码,它非常整洁。但我不太清楚如何使用它。我使用过StructureMap,它有一个静态的ObjectFactory。 Ninject有内核,但在Autofac的Google页面中,他们建议做这样的事情:

using( var resolver = builder.Build() ){
   var whatINeed = resolver.Resolve<INeedThisService>();
}

这是一个WinForms应用程序,所以我从上面做了一个无效对象状态,所以我转而使用全局IContainer,并且这样做了

 using( var resolver = Program.Container.CreateInnerContainer() )
 {
     var whatINeed = resolver.Resolve<INeedThisService>();
 }

我已经使用了大约3到5次。但这有效吗?或者我应该做一些像

这样的事情
 var whatINeed = Program.Resolve<INeedThisService>()

并在幕后

 internal static TServervice Resolver<TService>(){
       if(_container == null ) _container = builder.Build();
       return _container.Resolve<TService>();
 }

你会使用哪个,为什么?使用CreateInnerContainer()也会受到惩罚吗?

3 个答案:

答案 0 :(得分:9)

我不是AutoFac专家,但确实有其他Ioc容器的经验。我认为这个问题会给我一个尝试AutoFac的理由。

基于Ioc容器的设计应该努力将所有代码与访问容器隔离,除非在入口点或主机级别。我使用AutoFac和WinForms创建了以下示例,以显示表单如何通过它的构造函数访问服务。

我不太确定你为什么认为你需要内部容器。也许您可以发表评论,我可以提供更详细的回复。

static class Program
{
    [STAThread]
    static void Main()
    {
        var builder = new ContainerBuilder();
        builder.Register<TheService>().As<INeedThisService>();
        builder.Register(f => new Form1(f.Resolve<INeedThisService>())).As<Form1>();

        using (var container = builder.Build())
        {
            Application.Run(container.Resolve<Form1>());
        }

    }
}

public interface INeedThisService { }

public class TheService : INeedThisService
{
    public TheService() { Console.WriteLine("ctor ThisService"); }
}

public partial class Form1 : Form
{
    public Form1(INeedThisService service)
    {
        Console.WriteLine("ctor Form1");
        InitializeComponent();
    }
}

答案 1 :(得分:5)

1)从您给出的示例中,我可以假设您尝试将IOC容器主要用作服务定位器。虽然几乎所有容器都支持它,但主要用途是依赖注入。这意味着您应该完全避免调用Resolve方法,并让容器为您注入所有依赖项。其中两个(服务定位器和依赖注入)之间的差异超出了这个主题。

2)如果您仍想将其用作服务定位器,则可以在不创建内部容器的情况下使用根容器( Program.Container )。顺序是:

  • 创建ContainerBuilder
  • 在构建器中注册组件
  • 创建根容器:builder.Build()
  • 访问根容器以解析组件实例

3)容器层次结构在需要不同范围的单例行为的场景中非常有用:

  • Global \ Session \ Request(Web应用程序)
  • Application \ Plugin(基于桌面插件的应用程序)

BTW Autofac鼓励人们使用tagged contexts来解决此类问题:

答案 2 :(得分:3)

正如Mark Lindell指出的那样,您通常不需要直接在Autofac应用程序中访问容器。

建议的方法是在应用程序启动时像Mark一样访问它。

随后需要创建对象的其他组件可以声明一个IContext类型的构造函数参数,Autofac将自动注入该参数。

不需要依赖Autofac程序集的替代方法是使用Generated Factories,如下所述:http://code.google.com/p/autofac/wiki/DelegateFactories

希望这有帮助!