使用城堡windsor与拦截器和asp.net

时间:2011-01-24 14:42:10

标签: asp.net castle-windsor

我正在尝试使用纯粹的asp.net中的城堡windsor添加面向方面编程的日志记录,即不是MVC

我添加了一个实现IInterceptor接口的类和一个继承自Attribute的属性。

public class LogAttribute : Attribute
{
    public Level LogLevel { get; set; }

    public LogAttribute(Level level)
    {
        LogLevel = level;
    }
}

public class LoggingInterceptor : IInterceptor
{

    public void Intercept(IInvocation invocation)
    {

        MethodInfo mi = invocation.Method;
        LogAttribute[] atts = (LogAttribute[])mi.GetCustomAttributes(typeof(LogAttribute), true);
        // if method not marked with InternalUseRestricted attribute, then pass on call
        if (atts.Length == 0)
        {
            invocation.Proceed();
        }
        else
        {
            ISeiLogger log = LoggerFactory.GetLogger(mi.DeclaringType.ToString());
            //assume only one logging attribute
            //log on entry
            log.LogEnter(atts[0].LogLevel);
            //allow code to continue
            invocation.Proceed();
            //log on exit
            log.LogExit(atts[0].LogLevel);
        }
    }
}

现在在global.asax.cs中我添加了以下内容:

public partial class Global : System.Web.HttpApplication, IoCProvider
{

    private void InitializeIoC()
    {
        container = new WindsorContainer();
        container.Install(new Sei.Aspect.AspectInstaller());
    }

    public IWindsorContainer Container
    {
        get { return container; }
    }

    private static Sei.Logging.ISeiLogger log;
    private IWindsorContainer container;

    public override void Init()
    {
        base.Init();

        InitializeIoC();
    }

我已经创建了一个安装程序类:

public class AspectInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        //container.Register(AllTypes.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IInterceptor>().Configure(component => component.LifeStyle.PerWebRequest));
        container.Register(Component.For<IInterceptor>().ImplementedBy<LoggingInterceptor>().LifeStyle.PerWebRequest);
        container.Register(Component.For<IInterceptor>().ImplementedBy<InternalUseRestrictedInterceptor>().LifeStyle.PerWebRequest);
        container.Register(Component.For<IInterceptor>().ImplementedBy<CachingInterceptor>().LifeStyle.PerWebRequest);
    }
}

我现在想要将属性添加到一些仲裁页面后面的代码和一些任意虚拟方法,如

[Log(Level.Info)]
    protected string Login(string username, string password)
    {
        DoSomething();
    }

这显然不起作用。我是否需要更改我实例化页面(它的页面代码隐藏类)以使用容器的方式?或者这是我注册拦截器的方式?我希望能够在任何类中使用拦截器,而不必告诉容器我应用程序中的每个类。

1 个答案:

答案 0 :(得分:1)

简短的回答:这是不可能的。

答案很长:由于ASP.NET Web Forms的工作方式,它不会让任何人干扰页面实例化。有些人声称使用自定义PageHandlerFactory可以让你做IoC,但这只允许你在页面实例化之后设置属性,这对代理来说是不够的。

因此,运行时代理库(如DynamicProxy或LinFu)无法对此做任何事情。但您可以使用编译时方面编织器,例如PostSharp

或者,尽可能减少代码隐藏,将实际逻辑推迟到Windsor管理的组件。