Overriding dependencies that aren't IDependency

Topics: Customizing Orchard, Writing modules
Jul 21, 2011 at 1:51 PM

I have been playing about with Orchard trying to override an interface that isn't an IDependency but have not been able to get it to work. Is this even possible? I have been reading that there was a "low-level" autofac module hack used to override dependencies before the OrchardSuppressDependency attribute was introduced, but cannot find any examples or details about the hack.

More specifically, I am trying to override the OrchardLog4NetFactory (ILoggerFactory) and OrchardLog4netLogger (ILogger) as I want to write log entries to the database but do not want the connection string in the log4net.config file (rather I want to use content parts to store it in Orchard - this much I have managed, I just cannot retrieve it).

This is what I have tried:

1. Writing a custom appender for log4net - cannot retrieve connection string from Orchard as unable to resolve dependencies in this code

2. Custom appender that inherits from IShim to try and resolve the dependencies - seems to be totally incompatible with log4net

3. Creating an AutoFac module to register my own ILoggerFactory in the Load method - Orchard still uses the CastleLogger and OrchardLog4NetFactory registered in the Orchard LoggingModule

Can anyone provide more information on the so called "low-level" hack which might get this to work?

Jul 25, 2011 at 2:08 PM

Sorry to bump this up to the top again, but if what I am trying to do is not possible then I will know to stop even trying to work around this.

Coordinator
Jul 25, 2011 at 8:25 PM

When you tried #3 (which looks to me to be the most promising), did you put an OrchardSuppressDependency attribute on it?

Jul 26, 2011 at 9:32 AM

I'm not sure if I tried it at the time as I thought that only worked with IDependency classes, but I have just tested it out with the following set up and it still uses CastleLogger. Does everything look to be set up correctly?

public class LoggingSetupModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<TestLoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
        }
    }

    [OrchardSuppressDependency("Orchard.Logging.CastleLoggerFactory")]
    public class TestLoggerFactory : ILoggerFactory
    {
        public ILogger CreateLogger(Type type)
        {
            return new TestLogger();
        }
    }

    [OrchardSuppressDependency("Orchard.Logging.CastleLogger")]
    public class TestLogger : ILogger
    {
        public bool IsEnabled(LogLevel level)
        {
            return true;
        }

        public void Log(LogLevel level, Exception exception, string format, params object[] args)
        {
            
        }
    }

Jul 26, 2011 at 2:13 PM

I've run this code within the Orchard solution and can see that the LoggingModule's Load method is run twice as part of the HostInitialization method in Global.asax.cs

private static IOrchardHost HostInitialization(HttpApplication application) {
            var host = OrchardStarter.CreateHost(MvcSingletons);

            host.Initialize();

            // initialize shells to speed up the first dynamic query
            host.BeginRequest();
            host.EndRequest();

            return host;
        }

The module loads once in the call to CreateHost (creating the host container), at which point my custom module does not load, and once in the call to host.Initialize() when my custom module does load (during creation of the "shells").

Jul 26, 2011 at 2:44 PM
Edited Jul 26, 2011 at 2:44 PM

I have also found that this works without the Autofac module if I make ILoggerFactory an IDependency class and use the OrchardSuppressDependency attribute.

Jul 26, 2011 at 3:58 PM

I have created an issue and patch, changing ILoggerFactory to use ISingletonDependency.

http://orchard.codeplex.com/workitem/18037

Mar 19, 2014 at 3:57 PM
Hey, has there been any update to this issue? Or when the patch will be released?