简体   繁体   中英

Autofac Property Injection is always null

I am trying to register type with Autofac in console application. But it is always null when I call the implementation. Please guide. I dont wish to resolve it via container.

Here the issue is _dbFactory is always null .

public class DatabaseHelpers
{
    public IDatabaseFactory _dbFactory {get; set;}

    public void Execute(string commandText) 
    {
        var cmd = _dbFactory.CreateCommand();

        cmd.CommandText = commandText;
        cmd.CommandType = CommandType.Text;

        cmd.ExecuteNonQuery();
    }
}

console app code

static void Main(string[] args)
    {
        Register();

        var a = new DatabaseHelpers();

        a.Execute("test");
    }

    public static void Register()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<SqlFactory>().As<IDatabaseFactory>().InstancePerLifetimeScope() ;
        var container = builder.Build();
    }
}

I do not wish to resolve it using container and the calling the DatabaseHelpers methods from container like below. I just want to use the existing code in client by creating instance of DatabaseHelper

var app = container.Resolve<DatabaseHelper>();
container.Execute();

Any Ideas?

A partial answer, with many good hints, is already available through the various comments by SSS.

Let me add a little background.

You can consider Dependency Injection as a walled garden: your objective, when designing components, is to declare them with a complete list of dependencies, either as constructor parameters or properties, so you never ever have to call "new" inside your code. Except for the initial factory creation, of course.

Let me describe an example, about database management.

You can have many Service classes, which need access to a database. Needing access to a db, they require the presence of a DbConnection (in your example, a DbHelper, but let me show you the DbConnection case). So you add a constructor parameter of type DbConnection (or Func, if you want a delegate you can call multiple times to get multiple connections). Services are not concerned about how the DbConnection is built, they just DECLARE they need a valid connection.

public class MyService
{
    private readonly Func<DbConnection> _connectionGetter;
    private DbConnection _connection = null;
    public DbConnection Connection
    {
        get { return _connection ?? (_connection = _connectionGetter()); }
    }

    public MyService(Func<DbConnection> connectionGetter)
    {
        _connectionGetter = connectionGetter;
    }
}

Then you declare that a DbConnection is made by your factory class. Something like:

builder.Register<DbConnection>(c => c.Resolve<IDbFactory>().CreateConnection())
    .AsSelf()
    .InstancePerDependency();

And you register your factory as in a similar way.

In this way, you never call new, every dependency is kept by Autofac, and you're good to go. Just instantiate a container builder, which will in turn instantiate a main class (or a controller factory, if you're in MVC land), which will be configured automagically.

Some tips, in various order: - you can take a dependency (declare a property or constructor parameter) of type ILifetimeScope, if you need to resolve types directly in a service. - constructor parameter injection is preferrable, because the parameter list is easier to read and you have a complete list of dependencies, in only one place . The only case in which I would use property injection is for parameters in a base class, so the derived classes do not need to provide via constructor all the dependencies of the parent class.

I hope this can help you understand how DI is supposed to work.

Good luck with you code!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM