当然其他人已经让这两个人一起工作了。但由于某种原因,我不能。我对Castle来说比较新,但是我已经按照他们对如何添加它的解释。 Castle是用log4net 1.2.10构建的,所以我必须添加一个绑定重定向才能使它与1.2.11一起使用。
在我的代码中,失败发生在logger安装程序中:
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)
所以我看到问题是什么,但我似乎无法找到关于这个问题的任何内容,我无法想象我是唯一碰到它的人。
答案 0 :(得分:3)
我知道这是一个老问题,但我只是想添加一个替代解决方案,万一有人在努力解决同样的问题。我解决了它,没有添加任何绑定重定向,也没有引用两个版本的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一起使用。我有使用Castle Windsor 3.3.3的log4net 1.2.13。
答案 1 :(得分: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>
我不知道是否有更好的方法让它发挥作用,但这是有效的。
答案 2 :(得分:1)
Log4Net为次要版本更改了他们的公钥令牌,这可能很烦人,并引起了许多民间的悲痛。检查您的配置并阅读以下问题并回答
how do I work around log4net keeping changing publickeytoken
这可能不是你的问题或唯一的问题但是当我遇到类似的问题升级城堡和log4net时,这是我的主要悲痛。