Использование замка Виндзор с перехватчиками и asp.net - PullRequest
3 голосов
/ 24 января 2011

Я пытаюсь добавить протоколирование с аспектно-ориентированным программированием, используя замок Виндзор в простом asp.net, т.е. не MVC

Я добавил класс, который реализует интерфейс 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();
    }

Это, очевидно, не работает.Нужно ли мне изменить способ создания страницы (класс code-behind страницы) для использования контейнера?Или я так регистрирую перехватчики?Я хочу иметь возможность использовать перехватчики в любом классе в будущем, и мне не нужно сообщать контейнеру о каждом классе, который есть в моем приложении.

1 Ответ

1 голос
/ 24 января 2011

Краткий ответ: это невозможно.

Длинный ответ: благодаря тому, как работает ASP.NET Web Forms, он не позволяет никому вмешиваться в создание экземпляров страницы. Некоторые утверждают, что использование пользовательского PageHandlerFactory позволяет вам выполнять IoC, но это позволяет устанавливать свойства после создания страницы, чего просто недостаточно для прокси.

Так что прокси-библиотеки времени выполнения, такие как DynamicProxy или LinFu, ничего не могут с этим поделать. Но вы можете использовать ткачи во время компиляции, такие как PostSharp .

Кроме того, вы можете сделать свой код как можно более тонким, отложив фактическую логику до компонентов, управляемых Windsor.

...