开发者

Some questions on gettig started with autofac

开发者 https://www.devze.com 2023-02-01 04:32 出处:网络
I am just getting to grips with Autofac, and 开发者_高级运维have the following questions: Guice, for example, has its own annotations/ways when you pass parameters into constructors (they are handle

I am just getting to grips with Autofac, and 开发者_高级运维have the following questions:

  1. Guice, for example, has its own annotations/ways when you pass parameters into constructors (they are handled by Guice). Does autofac do anything similar? This is in th class definition, not when I instantiate the class.

  2. When I am using classes and want to get other types, do I setup the container each time (I am assuming this should be a static member?)?


1) Autofac does not require any specific mapping of constructors. It has one simple rule; it will inject as much as it can, but it must be able to resolve all parameters of at least one constructor. If there are no constructors with parameter types that are all known to Autofac, you'll get a runtime exception. You can set up Autofac to perform constructor or property injection, or a hybrid of both. The accepted best practice is to constructor-inject virtually everything; using property injection can give you an object that doesn't have all necessary dependencies, which you won't know has happened until you try to use the functionality requiring the missing dependency. If a dependency is expensive, must be factory-scoped (new instance for each request) and isn't always used by the dependent object, consider constructor-injecting a factory method that will lazily initialize this dependency.

2) How you set up the IoC container depends on how you plan to use it. A static or singleton instance of the IoC container is certainly a well-known use, but many say it's an anti-pattern, as it leads you down the slippery slope of using the container as a "service locator" (which makes you dependent on having an IoC container to do your dependency resolution; it's nice, but shouldn't be required). The generally-accepted pattern is to register all dependencies AND all objects needing a dependency with the container, and to only use the container at the highest level of object creation; all other objects will be a dependency of a top-level object and are either resolved as such or can be produced via factory method.

I went ahead and set my Autofac container up as a singleton, because the container basically exists to hydrate an instance of the main form of the application, which itself needs most of the dependencies registered with the IoC, and gets the rest of them anyway so it can pass them on to objects it will create. I could have registered all objects with the IoC and resolved child forms using factory methods, but I'd be replacing the dependency references with factory method references, and I would have probably ended up hooking up individual methods on the main form as factories for other windows.

EDIT: A code sample for 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
0

精彩评论

暂无评论...
验证码 换一张
取 消