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.
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);
}
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);
}