5

我读过 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() 也会受到惩罚吗?

4

3 回答 3

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();
    }
}
于 2009-06-10T19:30:04.420 回答
5

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

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

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

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

  • 全局\会话\请求(Web应用程序)
  • Application \ Plugin(基于桌面插件的应用程序)

BTW Autofac 鼓励人们使用标记上下文来解决此类问题:

于 2009-11-09T05:31:22.803 回答
3

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

推荐的方法是在应用程序启动时访问它一次,就像 Mark 所做的那样。

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

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

希望这可以帮助!

于 2009-08-01T20:44:01.160 回答