AOP拦截属性

时间:2009-12-01 14:54:38

标签: c# logging unity-container aop unity-interception

所以,我有这个问题,似乎没有人能够提供帮助。因此,不要继续抨击我会把它扔到那里寻找替代方法来抚摸这只特殊的猫。

我目前有以下内容:

public interface ICustomerService
{
    Customer GetCustomer(int id);
}

public class CustomerService : ICustomerService
{
    public Customer GetCustomer(int id)
    {
        ...
    }
}

...使用Unity我有IOC设置,同时配置拦截,如:

IUnityContainer ioc = new UnityContainer();
ioc.RegisterType<ICustomerService, CustomerService>()
    .Configure<Interception>()
    .SetInterceptorFor<ICustomerService>(new InterfaceInterceptor());

我想要实现的是能够在界面中放置属性,如下所示:

public interface ICustomerService
{
    [Log]
    Customer GetCustomer(int id);
}

...定义如下:

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

...然后在LogHandler类中执行我想要的所有日志记录:

public class LogHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        ... log stuff
    }
}

我想要实现的是跟踪/日志记录系统,其中处理程序记录正在调用的namespace.class.methodname,以及调用它的父namespace.class.methodname。我试过没有成功使用“输入”IMethodInvocation参数来获取我想要的信息,问题是,输入返回“ICustomerService”接口,同时检查父帧的堆栈帧返回父实现的类(例如.ServiceService)意思是当我尝试使用namespace.class.methodname作为实体ID创建树结构时,ID和parentID不匹配。

将参数拖放到[Log]属性中也无法正常工作,因为我可以放在那里?如果我输入接口名称,我仍然遇到与上面相同的问题,其中1的ID是接口而父接口是实现类。并且,我不能将实现类名称放在接口的属性中,因为它首先破坏了接口的目的!

所以,这就是困境。有人有新意吗?

2 个答案:

答案 0 :(得分:1)

我最终使用PostSharp来实现这样的日志记录。 http://www.postsharp.org

答案 1 :(得分:1)

我使用Unity和Interception进行日志记录工作。由于我可怕的缺乏配置设置技能,我不得不以编程方式进行。您需要设置至少一个拦截器,以及一个或多个策略对象。哦是的,UnityContainer.Configure<Interception>是至关重要的。

有点像这样:

// I'm using the TransparentProxyInterceptor because I want to trace EVERYTHING...
var intp = myUnityContainer.Configure<Interception>().
    SetInterceptorFor(typeof(MyTypeToLog), new TransparentProxyInterceptor());

var policy = intp.AddPolicy("somePolicyName");

policy.AddMatchingRule<TypeMatchingRule>(
    new InjectionConstructor(
        new InjectionParameter(typeof(MyTypeToLog)))
          .AddCallHandler(typeof(MyCallHandler), 
               new ContainerControlledLifetimeManager());

当然我也需要定义拦截调用处理程序:

public class MyCallHandler : ICallHandler, IDisposable
{
    public IMethodReturn Invoke(IMethodInvocation input, 
        GetNextHandlerDelegate getNext)
    {
        var methodReturn = getNext().Invoke(input, getNext);

        // log everything...
        LogMethodCall(input, methodReturn);

        // log exception if there is one...
        if (methodReturn.Exception != null)
        {
            LogException(methodReturn);
        }

        return methodReturn;
    }
}