【问题标题】:AOP interception attributeAOP 拦截属性
【发布时间】:2010-10-09 02:10:13
【问题描述】:

所以,我遇到了这个问题,似乎没有人能够提供帮助。因此,与其继续抨击,我将把它扔出去,寻找其他方法给这只猫剥皮。

我目前有以下:

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”接口,同时检查父级的堆栈帧返回父级的实现类(例如.CustomerService) 意味着当我尝试使用 namespace.class.methodname 作为实体 ID 创建树结构时,ID 和 parentID 不匹配。

将参数放入 [Log] 属性也不会真正起作用,因为我可以在其中放入什么?如果我输入接口名称,我仍然遇到与上面相同的问题,其中一个的 ID 是一个接口,而父级是实现类。而且,我不能将实现类名放在接口的属性中,因为这违背了首先拥有接口的目的!

所以,这就是两难境地。有人有新想法吗?

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 是的,我知道 PostSharp,但在我开始使用更多 dll 引用和工具使问题进一步复杂化之前,PostSharp 是否值得,更重要的是,我希望仅使用 Unity 和 Entlib 就可以实现?
    • 我不知道仅使用 Unity 和 Entlib 是否可行。我发现 PostSharp 使用起来非常简单,而且由于它是编译时 IL 修改,因此无需分发 PostSharp 程序集。
    【解决方案2】:

    我已经使用 Unity 和 Interception 进行日志记录。由于我极其缺乏配置设置技能,我不得不以编程方式进行。您需要设置至少一个拦截器,以及一个或多个策略对象。哦,是的,UnityContainer.Configure&lt;Interception&gt; 很关键。

    有点像这样:

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

    【讨论】:

      猜你喜欢
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 2010-09-10
      相关资源
      最近更新 更多