基本上,我试图为每个没有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/

10-17 01:34