1

当然,其他人已经让这两者一起工作了。但由于某种原因,我不能。我对 Castle 比较陌生,但我遵循了他们对如何添加它的解释。Castle 是使用 log4net 1.2.10 构建的,因此我必须添加绑定重定向才能使其与 1.2.11 一起使用。

在我的代码中,失败发生在记录器安装程序中:

public class LoggerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
    }
}

我得到一个 MissingMethodException :

void log4net.Config.XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo)

我不知道 log4net 是否已更改,但 ConfigureAndWatch 的签名是:

ICollection log4net.Config.XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo)

所以我知道问题出在哪里,但我似乎找不到任何关于这个问题的信息,我无法想象我是唯一遇到这个问题的人。

4

3 回答 3

4

我知道这是一个老问题,但我只是想添加一个替代解决方案,以防有人遇到同样的问题。我在没有添加任何绑定重定向并且没有引用两个版本的 log4net 的情况下解决了它。

首先确保卸载以下软件包(后者对 log4net 1.2.10 有硬依赖,我们希望使用最新的 log4net 版本):

Uninstall-Package Castle.Windsor-log4net
Uninstall-Package Castle.Core-log4net

确保您已安装 LoggingFacility 和 log4net(将 log4net 版本替换为所需版本):

Install-Package Castle.LoggingFacility
Install-Package log4net -Version 1.2.13

实现 AbstractLoggerFactory:

public class Log4NetFactory : Castle.Core.Logging.AbstractLoggerFactory
{
    internal const string DefaultConfigFileName = "log4net.config";

    public Log4NetFactory()
        : this(DefaultConfigFileName)
    {
    }

    public Log4NetFactory(string configFile)
    {
        var file = GetConfigFile(configFile);
        XmlConfigurator.ConfigureAndWatch(file);
    }

    public Log4NetFactory(bool configuredExternally)
    {
        if (configuredExternally)
        {
            return;
        }

        var file = GetConfigFile(DefaultConfigFileName);
        XmlConfigurator.ConfigureAndWatch(file);
    }

    public Log4NetFactory(Stream config)
    {
        XmlConfigurator.Configure(config);
    }

    public override ILogger Create(Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type");
        var log = LogManager.GetLogger(type);
        return new Log4netLogger(log, this);
    }

    public override ILogger Create(Type type, LoggerLevel level)
    {
        throw new NotSupportedException("Logger levels cannot be set at runtime. Please review your configuration file.");
    }

    public override ILogger Create(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");
        var log = LogManager.GetLogger(name);
        return new Log4netLogger(log, this);
    }

    public override ILogger Create(string name, LoggerLevel level)
    {
        throw new NotSupportedException("Logger levels cannot be set at runtime. Please review your configuration file.");
    }
}

实现 ILogger 接口:

[Serializable]
public class Log4netLogger : MarshalByRefObject, Castle.Core.Logging.ILogger
{
    private static readonly Type DeclaringType = typeof(Log4netLogger);

    public Log4netLogger(ILogger logger, Log4NetFactory factory)
    {
        Logger = logger;
        Factory = factory;
    }

    internal Log4netLogger()
    {
    }

    internal Log4netLogger(ILog log, Log4NetFactory factory)
        : this(log.Logger, factory)
    {
    }

    public bool IsDebugEnabled
    {
        get { return Logger.IsEnabledFor(Level.Debug); }
    }

    public bool IsErrorEnabled
    {
        get { return Logger.IsEnabledFor(Level.Error); }
    }

    public bool IsFatalEnabled
    {
        get { return Logger.IsEnabledFor(Level.Fatal); }
    }

    public bool IsInfoEnabled
    {
        get { return Logger.IsEnabledFor(Level.Info); }
    }

    public bool IsWarnEnabled
    {
        get { return Logger.IsEnabledFor(Level.Warn); }
    }

    protected internal Log4NetFactory Factory { get; set; }

    protected internal ILogger Logger { get; set; }

    public override string ToString()
    {
        return Logger.ToString();
    }

    public virtual Castle.Core.Logging.ILogger CreateChildLogger(string name)
    {
        return Factory.Create(Logger.Name + "." + name);
    }

    public void Debug(string message)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, message, null);
        }
    }

    public void Debug(Func<string> messageFactory)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, messageFactory.Invoke(), null);
        }
    }

    public void Debug(string message, Exception exception)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, message, exception);
        }
    }

    public void DebugFormat(string format, params Object[] args)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
        }
    }

    public void DebugFormat(Exception exception, string format, params Object[] args)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
        }
    }

    public void DebugFormat(IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(formatProvider, format, args), null);
        }
    }

    public void DebugFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsDebugEnabled)
        {
            Logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(formatProvider, format, args), exception);
        }
    }

    public void Error(string message)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, message, null);
        }
    }

    public void Error(Func<string> messageFactory)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, messageFactory.Invoke(), null);
        }
    }

    public void Error(string message, Exception exception)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, message, exception);
        }
    }

    public void ErrorFormat(string format, params Object[] args)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
        }
    }

    public void ErrorFormat(Exception exception, string format, params Object[] args)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
        }
    }

    public void ErrorFormat(IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(formatProvider, format, args), null);
        }
    }

    public void ErrorFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsErrorEnabled)
        {
            Logger.Log(DeclaringType, Level.Error, new SystemStringFormat(formatProvider, format, args), exception);
        }
    }

    public void Fatal(string message)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, message, null);
        }
    }

    public void Fatal(Func<string> messageFactory)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, messageFactory.Invoke(), null);
        }
    }

    public void Fatal(string message, Exception exception)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, message, exception);
        }
    }

    public void FatalFormat(string format, params Object[] args)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
        }
    }

    public void FatalFormat(Exception exception, string format, params Object[] args)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
        }
    }

    public void FatalFormat(IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(formatProvider, format, args), null);
        }
    }

    public void FatalFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsFatalEnabled)
        {
            Logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(formatProvider, format, args), exception);
        }
    }

    public void Info(string message)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, message, null);
        }
    }

    public void Info(Func<string> messageFactory)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, messageFactory.Invoke(), null);
        }
    }

    public void Info(string message, Exception exception)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, message, exception);
        }
    }

    public void InfoFormat(string format, params Object[] args)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
        }
    }

    public void InfoFormat(Exception exception, string format, params Object[] args)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
        }
    }

    public void InfoFormat(IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(formatProvider, format, args), null);
        }
    }

    public void InfoFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsInfoEnabled)
        {
            Logger.Log(DeclaringType, Level.Info, new SystemStringFormat(formatProvider, format, args), exception);
        }
    }

    public void Warn(string message)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, message, null);
        }
    }

    public void Warn(Func<string> messageFactory)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, messageFactory.Invoke(), null);
        }
    }

    public void Warn(string message, Exception exception)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, message, exception);
        }
    }

    public void WarnFormat(string format, params Object[] args)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
        }
    }

    public void WarnFormat(Exception exception, string format, params Object[] args)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
        }
    }

    public void WarnFormat(IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(formatProvider, format, args), null);
        }
    }

    public void WarnFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
    {
        if (IsWarnEnabled)
        {
            Logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(formatProvider, format, args), exception);
        }
    }
}

在 WindsorInstaller 中注册自定义 Log4NetFactory:

public class LoggerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.AddFacility<LoggingFacility>(x =>
            x.WithConfig(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)
            .ToLog("MyLogger")
            .LogUsing<Log4NetFactory>());
    }
}

将通常的 log4net 配置添加到您的 app/web.config - 如果还没有的话。

确保 log4net 配置中存在“MyLogger”,例如

<logger name="MyLogger" additivity="false">
  <level value="DEBUG" />
  <appender-ref ref="MyAppender" />
</logger>

现在您可以像这样注入 ILogger:

public class MyClass
{
    public MyClass(ILogger logger)
    {
        logger.Info("Castle Windsor with newest log4net.");
    }
}

使用上述方法,您可以将任何版本的 log4net 与 Castle Windsor 一起使用。我有 log4net 1.2.13 与 Castle Windsor 3.3.3 一起使用。

于 2015-06-24T07:16:28.950 回答
2

我必须将应用程序配置为使用两个版本的 log4net:

<configuration>
  <runtime>
     <assemblyBinding>
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" />
        <codeBase version="1.2.11.0" href="..\packages\log4net.2.0.0\lib\net40-full\log4net.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" />
        <codeBase version="1.2.10.0" href="..\packages\log4net.1.2.10\lib\2.0\log4net.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

我不知道是否有更好的方法让它工作,但这有效。

于 2012-10-17T06:54:13.753 回答
1

Log4Net 为次要版本更改了他们的公钥令牌,这可能很烦人,并引起了许多人的悲痛。检查您的配置并阅读以下问题和答案

我如何解决 log4net 不断变化的 publickeytoken

这可能不是您的问题或唯一的问题,但是当我在升级城堡和 log4net 时遇到类似的问题时,这是我的主要悲痛。

于 2012-10-16T21:27:55.853 回答