2011-01-24 111 views
3

我试图以纯asp.net使用温莎城堡面向方面编程,即添加日志记录不MVC使用温莎城堡与拦截器和asp.net

我添加了实现IInterceptor接口的类以及从属性继承的属性。

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

简答:这是不可能的。

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

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

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