2

基本的に、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インストーラー/ファシリティ、MonorailWindsorファシリティを追加してすべてを登録する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)));
            }
        }
    }

唯一の問題?インターセプターは登録されません!少なくとも、この単体テストによると:

[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));
            }
        }
4

1 に答える 1

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.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>());
        }
    }
}
于 2013-01-16T17:42:39.027 に答える