拦截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 执行相同的操作。
干杯。 贾斯。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
遗憾的是,您无法通过 Unity 拦截在 ASP.NET 页面中实现此功能。
Unity 拦截使用运行时拦截模型。根据您选择的拦截器,您将获得具有虚拟方法重写的子类来调用调用处理程序 (VirtualMethodInterceptor),或者获得一个单独的代理对象(Interface 或透明代理拦截器),该对象执行调用处理程序,然后转发到真实对象。
问题是 ASP.NET 控制页面的创建和调用,并且没有简单的方法来连接它们。如果不控制页面对象的创建,则无法使用 VirtualMethodInterceptor,因为这需要实例化子类。而且你也不能使用代理版本,因为你需要ASP.NET通过代理进行调用。
PostSharp 解决了这个问题,因为它实际上在编译时重写了 IL。
假设您可以挂钩页面对象的创建,则必须在此处使用 VirtualMethodInterceptor。它是一个私有方法,因此您需要记录“自我”调用(从对象的一个方法调用同一对象上的另一个方法)。基于代理的拦截器看不到这些,因为代理是一个单独的实例。
我希望有一个钩子可以自定义 ASP.NET 创建对象的方式 - 也许是 BuildManager?但我对细节了解不够,我预计这需要一些相当严重的黑客攻击才能完成。
那么,你如何解决这个问题呢?我的建议(实际上,无论如何我都会建议这样做)是对 ASP.NET 页面使用模型-视图-演示者模式。使页面对象本身变得愚蠢。它所做的只是将调用转发到一个单独的对象,即 Presenter。 Presenter 是您真正的逻辑所在,并且独立于 ASP.NET 的细节。您在可测试性方面获得了巨大的进步,并且您可以拦截演示者上的调用,而不会遇到 ASP.NET 给您带来的所有困难。
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.