使用Autofac会有什么优缺点

时间:2021-12-12 22:55:37

I've read about Autofac that it's fast. I've seen the coding involved and it's pretty neat. But I'm not quite sure how to use it. I've used StructureMap, and it has a static ObjectFactory. Ninject has the Kernel, but in Autofac's Google pages they recommend doing something like this :

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

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

It's a WinForms app, so I got an Invalid Object state from doing the above, so I switched to having a global IContainer, and did it this way

它是一个WinForms应用程序,所以我从上面做了一个Invalid Object状态,所以我转而使用了一个全局的IContainer,并且这样做了

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

I've used it about 3 or 5 times. But is that efficient? Or should I just do something like

我用了大约3到5次。但这样有效吗?或者我应该做些什么

 var whatINeed = Program.Resolve<INeedThisService>()

and under the covers

并在幕后

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

Which would you use, and why? Also is there a penalty for working with CreateInnerContainer()?

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

3 个解决方案

#1


I am not an AutoFac expert but do have experience with other Ioc containers. I thought this question would give me a reason to try AutoFac.

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

Designs based on Ioc containers should strive to isolate all code from having access to the container except at the entry point or host level. I created the following example using AutoFac and WinForms to show how a form could access a service via it's constructor.

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

I'm not quite sure why you thought you needed the inner container. Perhaps you could comment and I can provide a more detailed response.

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

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();
    }
}

#2


1) From the examples you gave I could make an assumption that you are trying to use IOC container primarily as service locator. Although almost all containers support it, main usage would be Dependency Injection. That means you should avoid calling Resolve method at all and let container inject all dependencies for you. The differences between two of them (Service Locator and Dependency Injection) is beyond this topic.

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

2) If you still want to use it as service locator you can just use root container (Program.Container in your case) without creating inner containers. The sequence would be:

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

  • Create ContainerBuilder
  • Register you components in the builder
  • 在构建器中注册组件

  • Create root container: builder.Build()
  • 创建根容器:builder.Build()

  • Access root container to resolve component instances
  • 访问根容器以解析组件实例

3) Container hierarchies can be useful in the scenarios where you need singleton behaviour in different scopes:

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

  • Global \ Session \ Request (Web applications)
  • Global \ Session \ Request(Web应用程序)

  • Application \ Plugin (Desktop plugin-based applications)
  • Application \ Plugin(基于桌面插件的应用程序)

BTW Autofac encourage people to use tagged contexts to solve such problems:

BTW Autofac鼓励人们使用标记的上下文来解决这些问题:

#3


As Mark Lindell pointed out, you don't generally need to access the container directly in an Autofac application.

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

The recommended approach is to access it once, as Mark has done, when the application starts up.

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

Other components that subsequently need to create objects can declare a constructor parameter of type IContext, which Autofac will automatically inject.

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

An alternative, that does not require any dependency on the Autofac assembly, is to use Generated Factories as described at: http://code.google.com/p/autofac/wiki/DelegateFactories

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

Hope this helps!

希望这可以帮助!

#1


I am not an AutoFac expert but do have experience with other Ioc containers. I thought this question would give me a reason to try AutoFac.

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

Designs based on Ioc containers should strive to isolate all code from having access to the container except at the entry point or host level. I created the following example using AutoFac and WinForms to show how a form could access a service via it's constructor.

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

I'm not quite sure why you thought you needed the inner container. Perhaps you could comment and I can provide a more detailed response.

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

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();
    }
}

#2


1) From the examples you gave I could make an assumption that you are trying to use IOC container primarily as service locator. Although almost all containers support it, main usage would be Dependency Injection. That means you should avoid calling Resolve method at all and let container inject all dependencies for you. The differences between two of them (Service Locator and Dependency Injection) is beyond this topic.

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

2) If you still want to use it as service locator you can just use root container (Program.Container in your case) without creating inner containers. The sequence would be:

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

  • Create ContainerBuilder
  • Register you components in the builder
  • 在构建器中注册组件

  • Create root container: builder.Build()
  • 创建根容器:builder.Build()

  • Access root container to resolve component instances
  • 访问根容器以解析组件实例

3) Container hierarchies can be useful in the scenarios where you need singleton behaviour in different scopes:

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

  • Global \ Session \ Request (Web applications)
  • Global \ Session \ Request(Web应用程序)

  • Application \ Plugin (Desktop plugin-based applications)
  • Application \ Plugin(基于桌面插件的应用程序)

BTW Autofac encourage people to use tagged contexts to solve such problems:

BTW Autofac鼓励人们使用标记的上下文来解决这些问题:

#3


As Mark Lindell pointed out, you don't generally need to access the container directly in an Autofac application.

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

The recommended approach is to access it once, as Mark has done, when the application starts up.

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

Other components that subsequently need to create objects can declare a constructor parameter of type IContext, which Autofac will automatically inject.

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

An alternative, that does not require any dependency on the Autofac assembly, is to use Generated Factories as described at: http://code.google.com/p/autofac/wiki/DelegateFactories

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

Hope this helps!

希望这可以帮助!