1

首先,我之前从来没有用过Unity...我想通过unity拦截的方式将Tracing/Logging引入我们的项目。
该项目相当大(〜30000个文件)。目标是每次我们尝试调用外部服务时跟踪性能/执行周期。遗憾的是我不能使用任何其他库。
为了熟悉这个概念是如何工作的,我构建了一个我在 MSDN 上找到的小程序;但是我对日志属性的拦截仍然没有触发。我确定我缺少一些配置或/和初始化。我很感激任何帮助。

这是我的主程序:

namespace calc
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var t = new calc.Calculator.Calculator().Sub(5, 8);
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
            }
        }
     }
}

这是计算器类:

namespace calc.Calculator
{
    public interface ICalculator
    {
        Int32 Sum(Int32 x, Int32 y);        
        Int32 Sub(Int32 x, Int32 y);
    }

    public class Calculator : ICalculator
    {        
        public Int32 Sum(Int32 x, Int32 y)
        {
            return x + y;
        }

        [NonNegativeCallHandler] // Intercept this method and run tracing on it
        public Int32 Sub(Int32 x, Int32 y)
        {
            return x - y;
        }
    }
}

这是我的呼叫处理程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace calc.Tracing
{
    public class NonNegativeCallHandler : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input,
                                GetNextHandlerDelegate getNext)
        {
            // Perform the operation
            var methodReturn = getNext().Invoke(input, getNext);

            // Method failed, go ahead
            if (methodReturn.Exception != null)
                return methodReturn;

            // If the result is negative, then throw an exception
            var result = (Int32)methodReturn.ReturnValue;

            if (result < 0)
            {
                var exception = new ArgumentException("...");
                var response = input.CreateExceptionMethodReturn(exception);

                // Return exception instead of original return value
                return response;
            }

            return methodReturn;
        }

        public int Order { get; set; }
    }
}

最后

*这是我的属性定义:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;

namespace calc.Tracing
{
     public class NonNegativeCallHandlerAttribute : HandlerAttribute
     {
         public override ICallHandler CreateHandler(IUnityContainer container)
         {
             return new NonNegativeCallHandler();
         }
     }
}

我还需要添加什么以及在哪里(配置文件或内部构造函数等)才能使此代码正常工作。

4

2 回答 2

0

您的代码看起来来自Dino Esposito 的这篇文章。看起来您错过了配置部分(使用流畅代码或通过配置添加策略的段落)。


更新

你看过MSDN 上的这个页面吗?

于 2012-04-23T06:44:28.950 回答
0

我找到了一种解决方案……我已经修改了我的程序类来注册容器……而且看起来根本不需要额外的配置。这是修改后的程序:

namespace calc
{
class Program
{
    static void Main(string[] args)
    {
        ICalculator iCal;
        try
        {

            iCal = ConfigurePolicyInjectionWithUnity();

            var t = iCal.Sub(8, 5);
        }
        catch (Exception ex)
        {
            System.Console.WriteLine(ex.Message);
        }
    }

    static ICalculator ConfigurePolicyInjectionWithUnity()
    {
        IUnityContainer container = new UnityContainer();

        container.AddNewExtension<Interception>();
        container.RegisterType<ICalculator, 
                           calc.Calculator.Calculator>().Configure<Interception>()
            .SetInterceptorFor<ICalculator>(new InterfaceInterceptor());

            // resolve
            return container.Resolve<ICalculator>(); ;
        }
    }
}

现在,问题来了……假设我有大约 20 种不同风格的计算器,每个类都有大约 3-4 种方法可以跟踪。这些方法中的每一个都有唯一的签名。所以 3-4 个方法 x 20 个类 = ~80 个具有唯一签名的方法要被追踪。我的意思是我不能有一个接口来描述所有这些方法......从上面的解决方案中,至少在我的情况下,看起来我每个类都必须有一个接口才能实现拦截器。仅仅为了记录日志而引入 20-30 个新接口看起来不太优雅。在这种情况下,使用拦截和只使用一些辅助类来进行日志记录没有区别。我对么?

有没有其他方法可以在不定义接口的情况下使用拦截?我所需要的只是能够记录方法开始运行的时间以及它们完成执行的时间。

任何帮助或想法将不胜感激。

于 2012-04-26T04:13:18.973 回答