Using castle windsor with interceptors and asp.net

此生再无相见时 提交于 2019-12-10 19:08:14

问题


I'm trying to add logging with aspect orientated programming using castle windsor in plain asp.net, i.e. not MVC

I've added a class that implements the IInterceptor interface and an attribute that inherits from 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);
        }
    }
}

Now in the global.asax.cs I've added the following:

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();
    }

and I've created an installer class:

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

I now want to add the attribute to some arbitary page's code behind class and some arbitary virtual method, as in

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

This obviously doesn't work. Do I need to change the way I'm instantiating the page (its a page's code-behind class) to use a container? Or is it the way I'm registering the interceptors? I want to be able to use the interceptors on any class going forward and not have to tell the container about each and every class that I have in my application.


回答1:


Short answer: it's not possible.

Long answer: due to the way ASP.NET Web Forms works, it doesn't let anyone interfere with the page instantiation. Some claim that using a custom PageHandlerFactory lets you do IoC, but this only lets you set properties after the page has been instantiated, which is simply not enough for proxying.

So runtime proxy libraries such as DynamicProxy or LinFu can't do anything about this. But you may be able to use compile-time aspect weavers, such as PostSharp.

Alternatively, make your code-behind as slim as possible, deferring actual logic to Windsor-managed components.



来源:https://stackoverflow.com/questions/4783287/using-castle-windsor-with-interceptors-and-asp-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!