截取没有接口的Unity 2.0 HandlerAttribute [英] Intercept Unity 2.0 HandlerAttribute without an interface

查看:136
本文介绍了截取没有接口的Unity 2.0 HandlerAttribute的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Unity 2.0的AOP功能的首次用户,并且需要一些建议.我的目标是能够在ASPX页面中记录方法调用,如下所示:

public partial class Page2 : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        [Log]
        private void Testing()
        {

        }
    }

这是LogAttribute的代码:

public class LogAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LogHandler(Order);
    }
}

现在LogHandler:

public class LogHandler : ICallHandler
{
    public LogHandler(int order)
    {
        Order = order;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        string className = input.MethodBase.DeclaringType.Name;
        string methodName = input.MethodBase.Name;

        string preMethodMessage = string.Format("{0}.{1}", className, methodName);
        System.Diagnostics.Debug.WriteLine(preMethodMessage); 

        return getNext()(input, getNext);
    }

    public int Order { get; set; }
}

我遇到的问题是如何使用[Log]属性.我已经看到了很多有关如何配置拦截设置的示例,例如:

container.AddNewExtension<Interception>();
container.Configure<Interception>().SetDefaultInterceptorFor<ILogger>(new InterfaceInterceptor());

但这意味着我有一个要拦截的接口,而我没有.我有一个使用[Log]属性的ASPX页面.

那么如何配置Unity以使用[Log]属性?在使用PostSharp之前,我已经完成了此操作,并且希望能够使用Unity进行相同的操作.

干杯. 贾斯.

解决方案

很遗憾,您不会通过Unity拦截将其用于ASP.NET页面.

统一拦截使用运行时拦截模型.根据您选择的拦截器的不同,您将获得具有虚拟方法覆盖的子类来调用调用处理程序(VirtualMethodInterceptor)或单独的代理对象(Interface或TransparentProxyInterceptor),该对象将执行调用处理程序,然后转发到实际对象./p>

这是问题所在-ASP.NET控制着页面的创建和调用,没有简单的方法可以将它们连接起来.如果不控制页面对象的创建,则不能使用VirtualMethodInterceptor,因为这需要实例化一个子类.而且您也不能使用代理版本,因为您需要ASP.NET才能通过代理进行调用.

PostSharp解决了这个问题,因为它实际上是在编译时重写您的IL.

假设您可以参与页面对象的创建,则必须在此处使用VirtualMethodInterceptor.这是一个私有方法,因此您需要登录自我"调用(从对象的一个​​方法到同一对象的另一个方法的调用).基于代理的拦截器看不到它们,因为代理是一个单独的实例.

我希望在某处有一个挂钩可以自定义ASP.NET如何创建对象-也许是BuildManager?但是我对这些细节还不够了解,我希望它需要一些相当严肃的黑客才能开始工作.

那么,您如何解决这个问题?我的建议(实际上,无论如何我还是会建议这样做)是对ASP.NET页面使用Model-View-Presenter模式.使页面对象本身变哑.它所做的只是将调用转发到一个单独的对象Presenter. Presenter是您真正的逻辑所在,并且独立于ASP.NET的细节.您可以极大地提高可测试性,并且可以拦截主持人上的呼叫,而无需ASP.NET带来的所有麻烦.

I'm a first-time user of the AOP features of Unity 2.0 and would like some advice. My goal is to be able to log method calls in an ASPX page, like so:

public partial class Page2 : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }

        [Log]
        private void Testing()
        {

        }
    }

Here is the code for the LogAttribute:

public class LogAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LogHandler(Order);
    }
}

Now the LogHandler:

public class LogHandler : ICallHandler
{
    public LogHandler(int order)
    {
        Order = order;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        string className = input.MethodBase.DeclaringType.Name;
        string methodName = input.MethodBase.Name;

        string preMethodMessage = string.Format("{0}.{1}", className, methodName);
        System.Diagnostics.Debug.WriteLine(preMethodMessage); 

        return getNext()(input, getNext);
    }

    public int Order { get; set; }
}

The problem I have is how to use the [Log] attribute. I've seen plenty of example of how to configure the interception settings, for example:

container.AddNewExtension<Interception>();
container.Configure<Interception>().SetDefaultInterceptorFor<ILogger>(new InterfaceInterceptor());

But this implies that I have an interface to intercept, which I don't. I have the ASPX page which uses the [Log] attribute.

so how can I configure Unity to make use of the [Log] attribute? I've done this before using PostSharp and would like to be able to use Unity to do the same.

Cheers. Jas.

解决方案

You're unfortunately not going to get this to work in an ASP.NET page with Unity interception.

Unity interception uses a runtime interception model. Depending on the interceptor you choose, you'll either get a subclass with virtual method overrides to call the call handlers (VirtualMethodInterceptor) or a separate proxy object (Interface or TransparentProxyInterceptor) which execute the call handlers and then forward to the real object.

Here's the issue - ASP.NET controls creation and calls to your page, and there's no easy way to hook into them. Without controlling the creation of the page object, you can't use the VirtualMethodInterceptor, because that requires that you instantiate a subclass. And you can't use the proxy version either, because you need ASP.NET to make calls through the proxy.

PostSharp gets around this because it's actually rewriting your IL at compile time.

Assuming you could hook into the creation of the page object, you'd have to use the VirtualMethodInterceptor here. It's a private method, so you want logging on "self" calls (calls from one method of the object into another method on the same object). The proxy-based interceptors can't see those, since the proxy is a separate instance.

I expect there is a hook somewhere to customize how ASP.NET creates object - BuildManager maybe? But I don't know enough about the details, and I expect it'll require some pretty serious hacking to get work.

So, how do you get around this? My recommendation (actually, I'd recommend this anyway) is to use the Model-View-Presenter pattern for your ASP.NET pages. Make the page object itself dumb. All it does is forward calls to a separate object, the Presenter. The Presenter is where your real logic is, and is independent of the details of ASP.NET. You get a huge gain in testability, and you can intercept calls on the presenter without all the difficulty that ASP.NET gives you.

这篇关于截取没有接口的Unity 2.0 HandlerAttribute的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆