需要记录日志的地方包括:进入方法的时候,传参的时候,统计执行时间,方法返回参数的时候,退出语句块的时候,出现异常的时候,等等。先来体验不使用Micirosoft Unity进行日志记录。
class Program
{static void Main(string[] args){Add(1, 2);Console.ReadKey();}private static int Add(int a, int b){int result = 0;
string temp = string.Empty;string returnValue = string.Empty;try
{//记录进入方法
Console.WriteLine("马上要执行方法了");
temp = string.Format("输入的参数为:a={0},b={1}", a, b);Console.WriteLine(temp);//统计方法执行时间
Stopwatch watch = new Stopwatch();
watch.Start();result = a + b;watch.Stop();Console.WriteLine("程序执行时间为{0}", watch.Elapsed);
//记录返回值
returnValue = string.Format("返回结果是:{0}", result);Console.WriteLine(returnValue);//记录方法执行接收
Console.WriteLine("方法执行结束");
}catch (Exception ex)
{//记录异常
Console.WriteLine(string.Format("异常信息是:{0},输入参数是:{1}", ex.ToString(), temp));throw;
}finally
{//记录异常处理
Console.WriteLine("异常已经被处理了");
}return result;
}}
以上,还是存在一些问题:
○ 违反了"DRY"原则,如果还有其它方法,需要不断地写记录的逻辑
○ 对阅读代码造成影响
○ 耗时
Microsoft Unity的出现就是解决以上问题。
○ Proxy object or derived class是Unity拦截器,在执行方法前后进行拦截
○ Behaviors Pipeline是拦截行为管道,通过API注册
○ Target Object or Original class method是进行拦截的目标对象
□ 引用Unity和Unity.Interception组件
输入关键字Unity,通过NuGet安装Unity。
输入关键字Unity.Interception,通过NuGet安装Unity Interception Extension。
安装完后,相关组件包括:
□ 自定义拦截器
自定义的拦截器必须实现IInterceptionBehavior接口。
public class MyInterceptionBehavior : IInterceptionBehavior{//返回拦截行为所需要的接口
public IEnumerable<Type> GetRequiredInterfaces()
{return Type.EmptyTypes;
}/// <summary>
/// 使用本方法实施拦截行为
/// </summary>
/// <param name="input">目标方法的参数</param>
/// <param name="getNext">在拦截管道中的拦截行为的委托</param>
/// <returns>目标方法的返回值</returns>
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{Console.WriteLine("hello,方法马上开始执行~~");
IMethodReturn msg = getNext()(input, getNext);Console.WriteLine("bye,方法执行完了");
return msg;
}//是否启用拦截
public bool WillExecute{get { return true; }}}
□ 定义一个计算的接口
public interface ICalculator{int Add(int value1, int value2);int Subtract(int value1, int value2);int Multiply(int value1, int value2);int Divide(int value1, int value2);}
□ 对接口实现
public class Calculator : ICalculator{public int Add(int value1, int value2){int res = value1 + value2;Console.WriteLine(res);return res;
}public int Subtract(int value1, int value2){int res = value1 - value2;return res;
}public int Multiply(int value1, int value2){int res = value1 * value2;return res;
}public int Divide(int value1, int value2){int res = value1 / value2;return res;
}}
□ 配置文件中配置Unity
<configuration><configSections><sectionname="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"/>
</configSections><unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="ICalculator" type="MyLogging.ICalculator, MyLogging"/><alias alias="Calculator" type="MyLogging.Calculator, MyLogging"/><alias alias="MyBehavior" type="MyLogging.MyInterceptionBehavior, MyLogging" /><sectionExtensiontype="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,
Microsoft.Practices.Unity.Interception.Configuration" />
<container><extension type="Interception"/>
<register type="ICalculator" mapTo="Calculator"><interceptor type="InterfaceInterceptor" />
<interceptionBehavior type="MyBehavior"/>
</register></container></unity></configuration>
以上,
○ 通过<alias>节点为接口和类设置别名
○ type="MyLogging.ICalculator, MyLogging"中,逗号前面是类名,逗号后面是程序集名称
□ 客户端调用
using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
class Program
{static void Main(string[] args){//加载UnityContainer
IUnityContainer container = new UnityContainer();
container = Microsoft.Practices.Unity.Configuration.UnityContainerExtensions.LoadConfiguration(container);//解析出接口
ICalculator calc = Microsoft.Practices.Unity.UnityContainerExtensions.Resolve<ICalculator>(container);//执行方法
int res = calc.Add(1, 2);
Console.ReadKey();}}
参考资料:
http://www.lm-tech.it/Blog/post/2011/10/18/How-to-use-the-Unity-Interception-Extension.aspx