简体   繁体   中英

Autofac Registration & Resolution Confusion

Having trouble determining how to register two instances of a concrete class with different parameter arguments that later need to resolve to different services. In my app I am outputting data from a model to a text file:

var builder = new ContainerBuilder();
builder.RegisterType<SqlConnection>()
    .WithParameter("connectionString", ConnectionString)
    .As<IDbConnection>();

builder.Register(c => new FileStream(".\cat.txt", FileMode.Create, FileAccess.ReadWrite))
    .As<FileStream>();
// how would I also register another file stream like this so that it can be used later on?
//builder.Register(c => new FileStream(".\dog.txt", FileMode.Create, FileAccess.ReadWrite))
//   .As<FileStream>();

// and would I need to alter this, or would it be able to resolve multiple streamwriters?
builder.Register(c => new StreamWriter(c.Resolve<FileStream>()) { AutoFlush = true })
    .As<StreamWriter>();
builder.Register(c =>
{
    var csvWriter = new CsvWriter(c.Resolve<StreamWriter>(), CultureInfo.InvariantCulture);
});

var container = builder.Build();

using (var scope = container.BeginLifetimeScope())
{
    var cnn = container.Resolve<IDbConnection>();
    var catRecords = cnn.Query<CatModel>("select * from dbo.Cat")
    container.Resolve<CsvWriter>().WriteRecords(catRecords);
    // how do I get the correct resolution here?
    //var dogRecords = cnn.Query<DogModel>("select * from dbo.Dog")
    //container.Resolve<CsvWriter>().WriteRecords(dogRecords);
}

How do I register and resolve correctly to incorporate the two files correctly? Do I needed to use a delegate factory? Keyed registration? I have read through the documentation quite a lot, but I'm having trouble figuring out what fits here.

Keyed Services

Implementation with keyed services

var builder = new ContainerBuilder();
builder.RegisterType<SqlConnection>()
    .WithParameter("connectionString", ConnectionString)
    .As<IDbConnection>();

builder.Register(c => new FileStream(".\cat.txt", FileMode.Create, FileAccess.ReadWrite))
    .Keyed<FileStream>("cat");
builder.Register(c => new FileStream(".\dog.txt", FileMode.Create, FileAccess.ReadWrite))
   .Keyed<FileStream>("dog");

builder.Register(c => new StreamWriter(c.ResolveKeyed<FileStream>("cat")) { AutoFlush = true })
    .Keyed<StreamWriter>("cat");
builder.Register(c => new StreamWriter(c.ResolveKeyed<FileStream>("dog")) { AutoFlush = true })
    .Keyed<StreamWriter>("dog");

builder.Register(c =>
{
    new CsvWriter(c.ResolveKeyed<StreamWriter>("cat"), CultureInfo.InvariantCulture);
}).Keyed<CsvWriter>("cat");
builder.Register(c =>
{
    new CsvWriter(c.ResolveKeyed<StreamWriter>("dog"), CultureInfo.InvariantCulture);
}).Keyed<CsvWriter>("dog");

var container = builder.Build();

using (var scope = container.BeginLifetimeScope())
{
    var cnn = container.Resolve<IDbConnection>();
    var catRecords = cnn.Query<CatModel>("select * from dbo.Cat")
    container.ResolveKeyed<CsvWriter>("cat").WriteRecords(catRecords);
    var dogRecords = cnn.Query<DogModel>("select * from dbo.Dog")
    container.ResolveKeyed<CsvWriter>("dog").WriteRecords(dogRecords);
}

Named Services + Autofac Module

Combining the solution above with an Autofac module to help adhere to DRY coding practices. Swapped keyed services for named services since that was more the intent. As a side note, CsvWriter (part of CsvHelper) automatically flushes the buffer when using WriteRecords . You will get better performance by setting AutoFlush = false on the StreamWriter.

public class FlatFileModule : Module
{
    protected readonly string _filePath;
    protected readonly string _recordType;

    public FlatFileModule(string FilePath, string RecordType)
    {
        _filePath = FilePath;
        _recordType = RecordType;
    }

    protected override void Load(ContainerBuilder builder)
    {
        builder.Register(c => 
            new StreamWriter(_filePath, false, Encoding.UTF8) 
            { 
                AutoFlush = false 
            })
            .Named<StreamWriter>(_recordType);

        builder.Register(c => 
            new CsvWriter(
               c.ResolveNamed<StreamWriter>(_dataType),
               CultureInfo.InvariantCulture)
            )
            .Named<IWriter>(_recordType);
    }
}

...

var builder = new ContainerBuilder();
builder.RegisterType<SqlConnection>()
    .WithParameter("connectionString", ConnectionString)
    .As<IDbConnection>();

builder.RegisterModule(new FlatFileModule(@".\cat.txt", "Cat"));
builder.RegisterModule(new FlatFileModule(@".\dog.txt", "Dog"));

var container = builder.Build();

using (var scope = container.BeginLifetimeScope())
{
    var cnn = container.Resolve<IDbConnection>();
    var catRecords = cnn.Query<CatModel>("select * from dbo.Cat")
    container.ResolveNamed<IWriter>("Cat").WriteRecords(catRecords);
    var dogRecords = cnn.Query<DogModel>("select * from dbo.Dog")
    container.ResolveNamed<IWriter>("Dog").WriteRecords(dogRecords);
}

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