AOP 在C#中的简单应用.docx
《AOP 在C#中的简单应用.docx》由会员分享,可在线阅读,更多相关《AOP 在C#中的简单应用.docx(23页珍藏版)》请在冰豆网上搜索。
AOP在C#中的简单应用
AOP在C#中的简单应用
简介
如果你很熟悉面向方面编程(AOP),你就会知道给代码增加“切面”可以使代码更清晰并且具有可维护性。
但是AOP通常都依赖于第三方类库或者硬编码的.net特性来工作。
虽然这些实现方式的好处大于它们的复杂程度,但是我仍然在寻找一种实现AOP的更为简单的方式,来试我的代码更为清晰。
我将它们单独移出来,并命名为AspectF。
AspectOrientedProgramming(AOP)的背景“切面”指的是那些在你写的代码中在项目的不同部分且有相同共性的东西。
它可能是你代码中处理异常、记录方法调用、时间处理、重新执行一些方法等等的一些特殊方式。
如果你没有使用任何面向切面编程的类库来做这些事情,那么在你的整个项目中将会遗留一些很简单而又重复的代码,它将使你的代码很难维护。
例如,在你的业务逻辑层有些方法需要被记录,有些异常需要被处理,有些执行需要计时,数据库操作需要重试等等。
所以,也许你会写出下面这样的代码。
[csharp]viewplaincopyprint?
publicboolInsertCustomer(stringfirstName,stringlastName,intage,
Dictionary<string,string>attributes)
{
if(string.IsNullOrEmpty(firstName))
thrownewApplicationException("firstnamecannotbeempty");
if(string.IsNullOrEmpty(lastName))
thrownewApplicationException("lastnamecannotbeempty");
if(age<0)
thrownewApplicationException("Agemustbenon-zero");
if(null==attributes)
thrownewApplicationException("Attributesmustnotbenull");
//Logcustomerinsertsandtimetheexecution
Logger.Writer.WriteLine("Insertingcustomerdata...");
DateTimestart=DateTime.Now;
try
{
CustomerDatadata=newCustomerData();
boolresult=data.Insert(firstName,lastName,age,attributes);
if(result==true)
{
Logger.Writer.Write("Successfullyinsertedcustomerdatain"
+(DateTime.Now-start).TotalSeconds+"seconds");
}
returnresult;
}
catch(Exceptionx)
{
//Tryoncemore,maybeitwasanetworkbliporsometemporarydowntime
try
{
CustomerDatadata=newCustomerData();
if(result==true)
{
Logger.Writer.Write("Successfullyinsertedcustomerdatain"
+(DateTime.Now-start).TotalSeconds+"seconds");
}
returnresult;
}
catch
{
//Failedonretry,safetoassumepermanentfailure.
//Logtheexceptionsproduced
Exceptioncurrent=x;
intindent=0;
while(current!
=null)
{
stringmessage=newstring(Enumerable.Repeat('\t',indent).ToArray())
+current.Message;
Debug.WriteLine(message);
Logger.Writer.WriteLine(message);
current=current.InnerException;
indent++;
}
Debug.WriteLine(x.StackTrace);
Logger.Writer.WriteLine(x.StackTrace);
returnfalse;
}
}
}publicboolInsertCustomer(stringfirstName,stringlastName,intage,
Dictionary<string,string>attributes)
{
if(string.IsNullOrEmpty(firstName))
thrownewApplicationException("firstnamecannotbeempty");
if(string.IsNullOrEmpty(lastName))
thrownewApplicationException("lastnamecannotbeempty");
if(age<0)
thrownewApplicationException("Agemustbenon-zero");
if(null==attributes)
thrownewApplicationException("Attributesmustnotbenull");
//Logcustomerinsertsandtimetheexecution
Logger.Writer.WriteLine("Insertingcustomerdata...");
DateTimestart=DateTime.Now;
try
{
CustomerDatadata=newCustomerData();
boolresult=data.Insert(firstName,lastName,age,attributes);
if(result==true)
{
Logger.Writer.Write("Successfullyinsertedcustomerdatain"
+(DateTime.Now-start).TotalSeconds+"seconds");
}
returnresult;
}
catch(Exceptionx)
{
//Tryoncemore,maybeitwasanetworkbliporsometemporarydowntime
try
{
CustomerDatadata=newCustomerData();
if(result==true)
{
Logger.Writer.Write("Successfullyinsertedcustomerdatain"
+(DateTime.Now-start).TotalSeconds+"seconds");
}
returnresult;
}
catch
{
//Failedonretry,safetoassumepermanentfailure.
//Logtheexceptionsproduced
Exceptioncurrent=x;
intindent=0;
while(current!
=null)
{
stringmessage=newstring(Enumerable.Repeat('\t',indent).ToArray())
+current.Message;
Debug.WriteLine(message);
Logger.Writer.WriteLine(message);
current=current.InnerException;
indent++;
}
Debug.WriteLine(x.StackTrace);
Logger.Writer.WriteLine(x.StackTrace);
returnfalse;
}
}
}你会看到上面只有两行关键代码,它调用了CustomerData实例的一个方法插入了一个Customer。
但去实现这样的业务逻辑,你真的很难去照顾所有的细节(日志记录、重试、异常处理、操作计时)。
项目越成熟,在你的代码中需要维护的这些“边边角角”就更多了。
所以你肯定经常会到处拷贝这些“样板”代码,但只在这些样板内写少了真是的东西。
这多不值!
你不得不对每个业务逻辑层的方法都这么做。
比如现在你想在你的业务逻辑层中增加一个UpdateCustomer方法。
你不得不再次拷贝所有的这些“样板”,然后将两行关键代码加入其中。
思考这样的场景,你需要做出一个项目级别的改变——针对如何处理异常。
你不得不处理你写的这“上百”的方法,然后一个一个地修改它们。
如果你想修改计时的逻辑,做法同样如此。
面向切面编程就可以很好地处理这些问题。
当你采用AOP,你会以一种很酷的方式来实现它:
[csharp]viewplaincopyprint?
[EnsureNonNullParameters]
[Log]
[TimeExecution]
[RetryOnceOnFailure]
publicvoidInsertCustomerTheCoolway(stringfirstName,stringlastName,intage,
Dictionary<string,string>attributes)
{
CustomerDatadata=newCustomerData();
data.Insert(firstName,lastName,age,attributes);
}[EnsureNonNullParameters]
[Log]
[TimeExecution]
[RetryOnceOnFailure]
publicvoidInsertCustomerTheCoolway(stringfirstName,stringlastName,intage,
Dictionary<string,string>attributes)
{
CustomerDatadata=newCustomerData();
data.Insert(firstName