I'm facing a rather puzzling situation with DryIoC.
OK, actually, this is the first time I use an IoC container, so I may just be misunderstanding everything: from dependency injection, to IoC containers, to DryIoC itself.
Still, I've been a professional programmer for quite some time, I have decent Googling skills, and I couldn't even find a similar problem exposed by someone else.
Let's say I have a class library which exposes these interfaces...
namespace Logging
{
public interface ILogger
{
void Info(string message);
}
public interface ILoggerFactory
{
ILogger CreateLogger(string name);
}
}
...and another class library implementing the above interfaces.
namespace Logging.Console
{
internal class ConsoleLogger : ILogger
{
readonly string _name;
public ConsoleLogger(string name)
{
_name = name;
}
void Info(string message) => System.Console.WriteLine($"[{_name}] {message}");
}
public class ConsoleLoggerFactory : ILoggerFactory
{
public ILogger CreateLogger(string name) => new ConsoleLogger(name);
}
}
Then a third library with other stuff I need:
namespace LibraryA
{
public interface IServiceA
{
// bla bla
}
public class ServiceA : IServiceA
{
// Implement service A
}
public interface IServiceB
{
// yada yada
}
public class ServiceB : IServiceB
{
// Implement service B
}
}
Finally, a class library using all libraries above to implement a coffee grinder (I love coffee!)
using Logging;
using LibraryA;
namespace Coffee
{
public interface ICoffeeGrinder
{
GrindCoffee(int grams);
}
public class CoffeeGrinder : ICoffeeGrinder
{
readonly ILogger _logger;
readonly IServiceA _serviceA;
readonly IServiceB _serviceB;
public CoffeeGrinder(ILoggerFactory loggerFactory, string loggerName,
IServiceA serviceA, IServiceB serviceB)
{
_logger = loggerFactory.CreateLogger(loggerName);
_serviceA = serviceA;
_serviceB = serviceB;
}
public GrindCoffee(int grams)
{
_logger.Info($"About to grind {grams}g of coffee...");
// Grind coffee
_logger.Info("Done grinding.");
}
}
}
An application may need more than one grinder, each with its own name, according to (for example) a configuration file.
Therefore I want to be able to specify loggerName
at resolve time, like this:
using Coffee;
using DryIoC;
using LibraryA;
using Logging;
using Logging.Console;
namespace MyApplication
{
class Program
{
static void Main()
{
using (var container = new Container())
{
container.Register<ILoggerFactory, ConsoleLoggerFactory>();
container.Register<IServiceA, ServiceA>();
container.Register<IServiceB, ServiceB>();
container.Register<ICoffeeGrinder, CoffeeGrinder>(
/* Maybe some magic here? */);
// This won't work
var grinder = container.Resolve<ICoffeeGrinder>("My grinder");
// Use grinder
}
}
}
}
In other words, how do I tell DryIoC that one or more constructor parameters are not dependencies, but must be specified at resolve time instead?
Resolve as Func<string, ICoffeeGrinder>
, this is not uncommon feature supported by major containers, e.g. Autofac. Here is DryIoc wiki on this topic.
var getGrinder = container.Resolve<Func<string, ICoffeeGrinder>>();
var grinder = getGrinder(name);
Btw, you may look into major feature list of many IoC/DI containers to save your time. This link is also available on DryIoc readme under Benchmarks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With