I am trying to achieve object construction as shown below,
using (var context = new DbContext())
{
var processor = new Processor(context, new Parser(context, new Logger(context)), new Logger(context));
}
but using Castle Windsor. I am using inline dependencies as the code shows below, but as the Castle Windsor documentation states "Inline dependencies don't get propagated" Castle Windsor passing arguments. How can I achieve this another way?
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
namespace IOCTesting
{
class Program
{
static void Main(string[] args)
{
using (var context = new DbContext())
{
var processor = new Processor(context, new Parser(context, new Logger(context)), new Logger(context));
}
var container = new WindsorContainer();
container
.Register(Component.For<IProcessor>()
.ImplementedBy<Processor>());
container
.Register(Component.For<IParser>()
.ImplementedBy<Parser>());
container
.Register(Component.For<ILogger>()
.ImplementedBy<Logger>());
//[1] Creating my scope object here. (context)
using (var context = new DbContext())
{
var processor = container.Resolve<IProcessor>(new { context = context });
}
}
}
public class DbContext : IDisposable
{
public void Dispose()
{
Console.WriteLine("DbContext disposed.");
}
}
public class Processor : IProcessor
{
private readonly DbContext _context;
private readonly ILogger _logger;
private readonly IParser _parser;
//Dependency context passed in is the same object within the scope. See [1]
public Processor(DbContext context, IParser parser, ILogger logger)
{
_context = context;
_parser = parser;
_logger = logger;
}
}
public class Parser : IParser
{
private readonly DbContext _context;
private readonly ILogger _logger;
//Dependency context passed in is the same object within the scope. See [1]
public Parser(DbContext context, ILogger logger)
{
_context = context;
_logger = logger;
}
}
public class Logger : ILogger
{
private readonly DbContext _context;
//Dependency context passed in is the same object within the scope. See [1]
public Logger(DbContext context)
{
_context = context;
}
}
public interface IProcessor
{
}
public interface IParser
{
}
public interface ILogger
{
}
}
You need to look at scoping; at the moment you're not specifying a scope so all dependencies will be singletons.
Register DBContext
along with ILogger
, IParser
, and IProcessor
all with the Scoped
lifestlye. E.G.
container.Register(Component.For<DBContext>()
.ImplementedBy<DBContext>()
.Lifestyle.Scoped);
Then you need to resolve your dependencies and use them within a scope. This would normally be managed in infrastructure, but at its simplest would look like this:
using(container.BeginScope())
{
var processor = container.Resolve<IProcessor>();
// use processor here.
}
Now a new DBContext
will be created per scope and disposed when the container scope ends. You don't have to worry about initialising the DBContext
or passing it to the Resolve
method.