Search code examples
c#castle-windsornlogcastle

Combining Castle Windsor version 4.0.0 and NLog using Castle Logging Facility


I am attempting to set up a new console application using Castle Windsor. I want to incorporate NLog into the application. However, whenever I try to run the application I get the following error when trying to add an NLog facility to the Windsor container.

The error I'm getting is:

Castle.MicroKernel.SubSystems.Conversion.ConverterException: Could not convert string 'Castle.Services.Logging.NLogIntegration.NLogFactory,Castle.Services.Logging.NLogIntegration,Version=4.0.0.0, Culture=neutral,PublicKeyToken=407dd0808d44fbdc' to a type. ---> System.IO.FileLoadException: Could not load file or assembly 'Castle.Services.Logging.NLogIntegration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
   at Castle.MicroKernel.SubSystems.Conversion.TypeNameConverter.GetType(String name)
   at Castle.MicroKernel.SubSystems.Conversion.TypeNameConverter.PerformConversion(String value, Type targetType)
   --- End of inner exception stack trace ---
   at Castle.MicroKernel.SubSystems.Conversion.TypeNameConverter.PerformConversion(String value, Type targetType)
   at Castle.MicroKernel.SubSystems.Conversion.DefaultConversionManager.PerformConversion(String value, Type targetType)
   at Castle.MicroKernel.SubSystems.Conversion.DefaultConversionManager.PerformConversion[TTarget](String value)
   at Castle.Facilities.Logging.LoggingFacility.GetLoggingFactoryType(LoggerImplementation loggerApi)
   at Castle.Facilities.Logging.LoggingFacility.CreateProperLoggerFactory(LoggerImplementation loggerApi)
   at Castle.Facilities.Logging.LoggingFacility.Init()
   at Castle.MicroKernel.Facilities.AbstractFacility.Castle.MicroKernel.IFacility.Init(IKernel kernel, IConfiguration facilityConfig)
   at Castle.MicroKernel.DefaultKernel.AddFacility(String key, IFacility facility)
   at Castle.MicroKernel.DefaultKernel.AddFacility(IFacility facility)
   at Castle.MicroKernel.DefaultKernel.AddFacility[T](Action`1 onCreate)
   at Castle.Windsor.WindsorContainer.AddFacility[T](Action`1 onCreate)
   at CastleWindsorNLogIntegration.MyWindsorInstaller.Install(IWindsorContainer container, IConfigurationStore store) in c:\users\mchaleg\documents\visual studio 2015\Projects\CastleWindsorNLogIntegration\CastleWindsorNLogIntegration\Program.cs:line 41
   at Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] installers, DefaultComponentInstaller scope)
   at Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] installers)
   at CastleWindsorNLogIntegration.Program.Main(String[] args) in c:\users\mchaleg\documents\visual studio 2015\Projects\CastleWindsorNLogIntegration\CastleWindsorNLogIntegration\Program.cs:line 17

which occurs when I try to the new logging facility to the Windsor container. The code that triggers the exception is shown here in the code snippet below. The error occurs in the class MyWindsorInstaller.

namespace CastleWindsorNLogIntegration
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var container = new WindsorContainer().Install(new MyWindsorInstaller());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }


    internal class MyWindsorInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            // The error occurs when running this line
            container.AddFacility<LoggingFacility>(f => f.LogUsing(LoggerImplementation.NLog)
                                                            .WithConfig("NLog.config"));

            container.Register(
                Component.For<IObjectGraphRoot>().ImplementedBy<ObjectGraphRoot>());
        }
    }


    internal interface IObjectGraphRoot
    {
        void Log();
    }


    internal class ObjectGraphRoot : IObjectGraphRoot
    {
        private ILogger _logger = NullLogger.Instance;

        public ILogger Logger
        {
            get { return _logger; }
            set { _logger = value; }
        }

        public void Log()
        {
            _logger.Info("Log something");
        }
    }
}

From what I can tell I have installed all the correct packages using NuGet. You can see the list of installed packages below. I've checked the dependencies for each package and everything seems to be correct. Can anyone explain what I'm doing wrong?

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Castle.Core" version="4.1.1" targetFramework="net452" />
  <package id="Castle.Core-NLog" version="4.1.1" targetFramework="net452" />
  <package id="Castle.LoggingFacility" version="4.0.0" targetFramework="net452" />
  <package id="Castle.Windsor" version="4.0.0" targetFramework="net452" />
  <package id="NLog" version="4.4.12" targetFramework="net452" />
  <package id="NLog.Config" version="4.4.12" targetFramework="net452" />
  <package id="NLog.Schema" version="4.4.12" targetFramework="net452" />
</packages>

Solution

  • The solution described below is taken from the information contained in the link https://www.bountysource.com/issues/47957245-fix-dependency-specification-of-logging-packages-to-the-exact-same-explicit-version-of-castle-core-package

    When originally installing the packages for Castle Windsor and NLog (via NuGet) I ended up with the following combination of packages:

    <package id="Castle.Core" version="4.0.0" targetFramework="net452"/>
    <package id="Castle.Core-NLog" version="3.3.0" targetFramework="net452" />
    <package id="Castle.LoggingFacility" version="4.0.0" targetFramework="net452"/>
    <package id="Castle.Windsor" version="4.0.0" targetFramework="net452"/>    
    <package id="Castle.Windsor-NLog" version="3.4.0" targetFramework="net452"/>
    

    The problem is happening because different versions of the separate Castle-Core packages should not be used together.

    The solution was to reload the packages (again via NuGet) and specify the same version for each package, as shown in the list below.

    <package id="Castle.Core" version="4.0.0" targetFramework="net452"/>
    <package id="Castle.Core-NLog" version="4.0.0" targetFramework="net452" />
    <package id="Castle.LoggingFacility" version="4.0.0" targetFramework="net452"/>
    <package id="Castle.Windsor" version="4.0.0" targetFramework="net452"/>    
    

    Note that Castle.Windsor-NLog is no longer required so it should not be installed.