基本上,我试图为每个没有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设施并注册所有内容的Monorail安装程序。控制器,视图组件和过滤器,最后是添加此功能的日志记录安装程序:
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)));
}
}
}
唯一的问题?没有拦截器被注册!根据此单元测试,Atleast:
[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));
}
}
最佳答案
尝试将您的设施更改为此:
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<AspectLogger>());
Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
}
private void Kernel_ComponentModelCreated(ComponentModel model)
{
if (
!(model.Implementation.GetProperties()
.Any(prop => prop.PropertyType.GetInterfaces().Contains(typeof(ILogger))) ||
model.Implementation.GetFields()
.Any(l => l.FieldType.GetInterfaces().Contains(typeof(ILogger)))))
{
model.Interceptors.AddIfNotInCollection(InterceptorReference.ForType<AspectLogger>());
}
}
}
另外,您应该改用IContributeComponentModelConstruction:http://docs.castleproject.org/Default.aspx?Page=ComponentModel-construction-contributors&NS=Windsor&AspxAutoDetectCookieSupport=1
它看起来像这样:
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<AspectLogger>());
Kernel.ComponentModelBuilder.AddContributor(new AddLoggingAspect());
}
}
public class AddLoggingAspect : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (
!(model.Implementation.GetProperties()
.Any(prop => prop.PropertyType.GetInterfaces().Contains(typeof(ILogger))) ||
model.Implementation.GetFields()
.Any(l => l.FieldType.GetInterfaces().Contains(typeof(ILogger)))))
{
model.Interceptors.AddIfNotInCollection(InterceptorReference.ForType<AspectLogger>());
}
}
}
关于c# - 如何向没有ILogger类型的字段或属性的组件正确添加拦截器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14340208/