DI Autofac design question

Topics: General
Jul 8, 2013 at 4:10 AM
Edited Jul 8, 2013 at 4:14 AM
I've looked at the LoggerModule which registers two types (Castle & Log4net) but I can't figure out how it decides which implementation to use. I'm a bit of a newbie to this, so let me take a step back for a moment.

We'll have multiple implementations of our interface, IPriceProvider.
    public interface IPriceProvider : IDependency{
        decimal GetPrice();
    }
Sample implementation (one of a number):
    public class AxPriceProvider : IPriceProvider
    {
        public decimal GetPrice() {
            return 3;
        }
    }
At the moment I'm doing property injection with a factory providing the run time implementation I want to use. Instead I'd like to be able to inject this via the constructor on a driver, but I need to be able to specify the implementation I want. Ideally I'd like to be able to 'register' that implementation in Orchard/autofac somehow and have it resolve upon injection.

(the implementation is base on a non-content item field accessed via IRepository, which works fine)

How should I approach this?
Coordinator
Jul 8, 2013 at 4:38 AM
Just inject an IEnumerable<IPriceProvider> instead of a IPriceProvider (preferably via constructor injection), and pick the one you want.
Jul 8, 2013 at 6:17 AM
is it ok to use this method:

builder.Register<OnlineState>().Named<IDeviceState>("online");

then use it

var r = container.ResolveNamed<IDeviceState>("online");
Coordinator
Jul 8, 2013 at 7:55 AM
You don't need to.
Jul 9, 2013 at 2:01 AM
Is it possible to simply inject a single <IPriceProvider> which calls, say, PriceProviderFactory which returns the implementation we want?

I suspect this is already done in LoggingModule.cs somehow.
        protected override void Load(ContainerBuilder moduleBuilder) {
            // by default, use Orchard's logger that delegates to Castle's logger factory
            moduleBuilder.RegisterType<CastleLoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
            moduleBuilder.RegisterType<OrchardLog4netFactory>().As<Castle.Core.Logging.ILoggerFactory>().InstancePerLifetimeScope();

            // call CreateLogger in response to the request for an ILogger implementation
            moduleBuilder.Register(CreateLogger).As<ILogger>().InstancePerDependency();
So two logger types are registered, how does it know which implementation to use?
Coordinator
Jul 9, 2013 at 2:38 AM
At this point I'm totally confused by what your scenario exactly is. If you want to specify what implementation to use, this is not IoC and you should just pass in an instance of the specific type you want.
Jul 9, 2013 at 2:57 AM
Apologies Bertrand, I changed direction a bit from the original question - my fault.

We we trying to figure out if there was a way to specify the implementation (when there is more than one) that would be resolved by autofac when doing constructor injection. Above in the logging code there are 2 types registered, but what determines which one will actually be used?
Coordinator
Jul 9, 2013 at 5:45 AM
It's kind of the point that as the consumer of the interface, you don't decide what implementation you get. It's the environment that decides. It does so based on order of dependencies between modules, OrchardSuppressDependency attributes, a few additional rules, and then order of declaration if all else fails. Again I must ask what exactly you are trying to do, as you rarely need to know...