关于autofac入门的一些问题

时间:2010-12-21 23:10:31

标签: .net autofac

我正在接触Autofac,并提出以下问题:

  1. 例如,当你将参数传递给构造函数时,Guice有自己的注释/方法(它们由Guice处理)。 autofac做类似的事吗?这是在类定义中,而不是在我实例化类时。

  2. 当我使用类并希望获得其他类型时,我是否每次都设置容器(我假设这应该是静态成员?)?

1 个答案:

答案 0 :(得分:6)

1)Autofac不需要构造函数的任何特定映射。它有一个简单的规则;它将尽可能多地注入,但它必须能够解析至少一个构造函数的所有参数。如果没有构造函数具有Autofac都知道的参数类型,那么您将获得运行时异常。您可以设置Autofac来执行构造函数或属性注入,或两者的混合。公认的最佳实践是建造者注入几乎所有东西;使用属性注入可以为您提供一个没有所有必需依赖项的对象,在您尝试使用需要缺少依赖项的功能之前,您不会知道这些依赖项。如果依赖项很昂贵,必须是工厂范围的(每个请求的新实例)并且并不总是由依赖对象使用,请考虑构造函数注入一个工厂方法,该方法将懒惰地初始化此依赖项。

2)如何设置IoC容器取决于您计划如何使用它。 IoC容器的静态或单例实例当然是一个众所周知的用途,但许多人说这是一种反模式,因为它会导致你使用容器作为“服务定位器”(这使你依赖于有一个IoC容器来进行依赖解析;它很好,但不应该被要求)。普遍接受的模式是注册所有依赖项和需要与容器相关的所有对象,并且仅在最高级别的对象创建时使用容器;所有其他对象将是顶级对象的依赖项,并且可以这样解析,也可以通过工厂方法生成。

我继续将我的Autofac容器设置为单例,因为容器基本上用于保存应用程序主要形式的实例,该实例本身需要在IoC中注册的大多数依赖项,并获得其余的无论如何它们都可以将它们传递给它将创建的对象。我可以用IoC注册所有对象并使用工厂方法解析子表单,但是我将用工厂方法引用替换依赖引用,我可能最终将主表单上的各个方法作为其他工厂连接起来窗户。

编辑:1)的代码示例:

public interface IDoSomething {...}
public interface IDoSomethingElse {...}

//the implementations don't have to be the same class, of course; 
//this is for simplicity
public class DoTwoThings: IDoSomething, IDoSomethingElse {...}

public class ExpensiveObject {...}

public class DependentClass
{
    public DependentClass(IDoSomething aDoer, IDoSomethingElse anotherDoer) {...}
}

public class DependsOnExpensiveObject
{
    private Func<ExpensiveObject> Factory;
    private ExpensiveObject instance;
    public DependsOnExpensiveObject(Func<ExpensiveObject> factoryMethod) 
    { Factory = factoryMethod; }

    public bool HasInstance { get{ return instance != null; } }

    public void ForceInitialize()
    {
        instance = Factory();
    }
}

...
//In your main method, or wherever
var builder = new ContainerBuilder()
builder.RegisterType<DoTwoThings>().As<IDoSomething>();
builder.Register<DependentClass>();
var container = builder.Build();

//This line of code will throw at runtime b/c IDoSomethingElse
//does not have an implementation registered with the container.
container.Resolve<DependentClass>();

//Now we'll register the other dependency; 
//dependencies can be registered and overwritten at will
builder.RegisterType<DoTwoThings>().As<IDoSomethingElse>();
builder.Update(container);

//This line will succeed now that we have a registration for IDoSomethingElse
container.Resolve<DependentClass>();

builder.RegisterType<ExpensiveClass>();
builder.RegisterType<DependsOnExpensiveClass>();
builder.Update(container);

//Autofac will provide a delegate that resolves an ExpensiveObject
var dependent = container.Resolve<DependsOnExpensiveClass>();

if(!dependent.HasInstance) //HasInstance returns false
    dependent.ForceInitialize();

Console.WriteLine(HasInstance); // True
相关问题