基本上,我正在尝试为每个没有 ILogger 属性或字段的类添加一个日志记录拦截器。
我正在使用的项目是使用 Monorail 2.1 和最新的 Castle Windsor 稳定版本(2012 年 8 月,3.1.0)构建的。
假设我有:
[ViewComponentDetails("Followers")]
public class FollowersComponent : ViewComponent
{
private readonly ISession NHibernateSession;
public FollowersComponent(ISession session)
{
NHibernateSession = session;
}
public override void Render()
{
IPrincipal loggedUser = EngineContext.CurrentUser;
if ((loggedUser.Identity.AuthenticationType == "Monorail Type") && (loggedUser.Identity.IsAuthenticated))
{
var user = (PrincipalAdapter<Int64>)Session["User"];
PropertyBag["loggedUser"] = NHibernateSession.Get<User>(user.UserId);
RenderView("Followers");
}
}
}
我想向这个类以及任何其他没有日志记录的类添加以下拦截器:
public class AspectLogger : IInterceptor
{
public AspectLogger(ILoggerFactory loggerFactory)
{
LoggerFactory = loggerFactory;
Loggers = new ThreadSafeDictionary<Type, ILogger>();
}
public ILoggerFactory LoggerFactory { get; private set; }
public ThreadSafeDictionary<Type, ILogger> Loggers { get; private set; }
public void Intercept(IInvocation invocation)
{
if (!Loggers.ContainsKey(invocation.TargetType))
{
Loggers.Add(invocation.TargetType, LoggerFactory.Create(invocation.TargetType));
}
ILogger logger = Loggers[invocation.TargetType];
if (logger.IsDebugEnabled) logger.Debug(invocation.PrettyPrint());
try
{
invocation.Proceed();
}
catch (Exception ex)
{
if (logger.IsErrorEnabled) logger.Error(invocation.PrettyPrint(), ex);
throw;
}
}
}
因此,使用 Windsor 网站上的文档和其他一些博客文章,我提出了以下安装程序和设施:一个 Nhibernate 安装程序/设施,它设置会话工厂和会话,一个单轨安装程序,它添加 Monorail Windsor 设施并注册所有控制器、视图组件和过滤器,最后是添加此功能的日志安装程序:
public class ExtendedLoggingFacility : LoggingFacility
{
public ExtendedLoggingFacility()
: base()
{
}
public ExtendedLoggingFacility(LoggerImplementation loggingApi) :
base(loggingApi)
{
}
public ExtendedLoggingFacility(LoggerImplementation loggingApi, string configFile) :
base(loggingApi, configFile)
{
}
public ExtendedLoggingFacility(string customLoggerFactory, string configFile) :
base(customLoggerFactory, configFile)
{
}
public ExtendedLoggingFacility(LoggerImplementation loggingApi, string customLoggerFactory, string configFile) :
base(loggingApi, customLoggerFactory, configFile)
{
}
protected override void Init()
{
base.Init();
Kernel.Register(Component.For<IInterceptor>()
.ImplementedBy<AspectLogger>());
Kernel.ComponentRegistered += Kernel_ComponentRegistered;
}
private void Kernel_ComponentRegistered(string key, IHandler handler)
{
if (!(handler.ComponentModel.Implementation.GetProperties().Any(prop => prop.PropertyType.GetInterfaces().Contains(typeof(ILogger))) || handler.ComponentModel.Implementation.GetFields().Any(l=>l.FieldType.GetInterfaces().Contains(typeof(ILogger)))))
{
handler.ComponentModel.Interceptors.AddIfNotInCollection(new InterceptorReference(typeof(AspectLogger)));
}
}
}
唯一的问题?没有拦截器被注册!至少,根据这个单元测试:
[TestFixture]
public class ControllersInstallerTests
{
private IWindsorContainer containerWithControllers;
[SetUp]
public void OnSetup()
{
containerWithControllers = new WindsorContainer()
.Install(FromAssembly.Containing(typeof(UserController)));
}
[Test]
public void All_components_which_dont_have_ILogger_as_a_property_or_field_have_an_AspectLog()
{
var allComponents = GetPublicClassesFromApplicationAssembly(p => !(p.GetProperties().Any(prop => prop.PropertyType.IsAssignableFrom(typeof(ILogger)) || p.GetFields().Any(g => g.FieldType.IsAssignableFrom(typeof(ILogger))))));
var allHandlers = GetAllHandlers(containerWithControllers);
foreach (var comp in allComponents)
{
var handlersForComponent = GetHandlersFor(comp, containerWithControllers);
if (handlersForComponent.Length != 0)
Assert.True(handlersForComponent.All(p => p.ComponentModel.HasInterceptors));
}
}