我读过关于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()也会受到惩罚吗?
答案 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 )。顺序是:
3)容器层次结构在需要不同范围的单例行为的场景中非常有用:
BTW Autofac鼓励人们使用tagged contexts来解决此类问题:
答案 2 :(得分:3)
正如Mark Lindell指出的那样,您通常不需要直接在Autofac应用程序中访问容器。
建议的方法是在应用程序启动时像Mark一样访问它。
随后需要创建对象的其他组件可以声明一个IContext类型的构造函数参数,Autofac将自动注入该参数。
不需要依赖Autofac程序集的替代方法是使用Generated Factories,如下所述:http://code.google.com/p/autofac/wiki/DelegateFactories
希望这有帮助!