我们将创建一个性能对我们来说非常重要的Web服务。因此我们决定了每种方法的测量编译时间。
我们希望拦截每个方法并记录编译时间。但是我们不想更改发布的代码。因此,我们如何才能使这个拦截器仅在调试模式下运行?
答案 0 :(得分:0)
这是拦截器,它计算一个类中的每个方法。 (它使用log4net)
internal class DurationCalculatorAspect : IMessageSink
{
public bool ExceptionHandlingEnabled { get; set; }
internal DurationCalculatorAspect(IMessageSink next,bool exceptionHandlingEnabled)
{
m_next = next;
ExceptionHandlingEnabled = exceptionHandlingEnabled;
}
private IMessageSink m_next;
#region IMessageSink implementation
public IMessageSink NextSink
{
get { return m_next; }
}
public IMessage SyncProcessMessage(IMessage msg)
{
var typeResolver = ((System.Type[])(((System.Collections.ArrayList)msg.Properties.Values)[2]));
var typeName = "void";
if(typeResolver.Count()!=0)
{
typeName = typeResolver[0].FullName;
}
var argsString = "";
var argArray =(object[])((System.Collections.ArrayList)msg.Properties.Values)[4];
for (int i = 0;i<argArray.Length;i++)
{
argsString+=(i+1).ToString() + ". Object : " +argArray[i];
}
Logger.GetLogger().Debug("MethodName : "+((System.Collections.ArrayList)msg.Properties.Values)[1]+"\r\n"+
"TypeName: " + typeName + "\r\n" + "Args : " + argsString
);
var date1 = DateTime.Now;
var returnMethod =
m_next.SyncProcessMessage(msg);
var returnMessage = ((IMethodReturnMessage)returnMethod);
var date2 = DateTime.Now;
Logger.GetLogger().Debug("MethodName : " + returnMessage.MethodName + "Duration : " + date2.Subtract(date1).TotalMilliseconds + " .ms"+"\r\n"+
"TypeName: " + typeName + "\r\nReturned : " +returnMessage.ReturnValue);
if (returnMessage.Exception != null)
{
Logger.GetLogger().Fatal("Exception : " + returnMessage.Exception.Data + " InnerException : " + returnMessage.Exception.InnerException);
if (ExceptionHandlingEnabled)
{
return new ReturnMessage(null, null);
}
}
return returnMethod;
}
public IMessageCtrl AsyncProcessMessage(IMessage msg,
IMessageSink replySink)
{
throw new InvalidOperationException();
}
#endregion //IMessageSink implementation
}
public class DurationCalculatorInterceptorProperty : IContextProperty,
IContributeObjectSink
{
public bool ExceptionHandlingEnabled { get; set; }
public DurationCalculatorInterceptorProperty(bool exceptionHandlingEnabled)
{
ExceptionHandlingEnabled = exceptionHandlingEnabled;
}
#region IContributeObjectSink implementation
public IMessageSink GetObjectSink(MarshalByRefObject o,
IMessageSink next)
{
return new DurationCalculatorAspect(next,ExceptionHandlingEnabled);
}
#endregion // IContributeObjectSink implementation
#region IContextProperty implementation
// Implement Name, Freeze, IsNewContextOK
#endregion //IContextProperty implementation
public void Freeze(Context newContext)
{
}
public bool IsNewContextOK(Context newCtx)
{
return true;
}
public string Name
{
get { return ""; }
}
}
[AttributeUsage(AttributeTargets.Class)]
public class DurationCalculatorInterceptorAttribute : ContextAttribute
{
public bool ExceptionHandlingEnabled { get; set; }
public DurationCalculatorInterceptorAttribute(bool exceptionHandlingEnabled) : base("Security")
{
ExceptionHandlingEnabled = exceptionHandlingEnabled;
}
public override void GetPropertiesForNewContext(
IConstructionCallMessage ccm)
{
ccm.ContextProperties.Add(new DurationCalculatorInterceptorProperty(ExceptionHandlingEnabled));
}
}
下面给出了两个使用拦截来记录持续时间和一个用于处理异常的类。这很奇怪,但使用此拦截器处理异常的速度要快28倍。但它仅对记录异常有用。另外,不要忘记继承ContextBoundObject的类。
[DurationCalculatorInterceptor(false)]
public class WithoutExceptionHandling : ContextBoundObject
{
public void DivideYeahWithoutExceptionHandling()
{
for (int i = 0; i < 1000000; i++)
{
try
{
var x = 2;
var y = 1;
var z = x / (y - 1);
}
catch (Exception)
{
}
}
}
}
[DurationCalculatorInterceptor(true)]
public class WithExceptionHandling : ContextBoundObject
{
public void DivideYeahWithExceptionHandling()
{
for (int i = 0; i < 1000000; i++)
{
var x = 2;
var y = 1;
var z = x / (y - 1);
}
}
}