postsharp
面向方面的编程? (Aspect Oriented Programming?)
所以首先要注意的是:What is Aspect Oriented Programming (AOP)?
什么是面向方面的编程(AOP)?
AOP is a coding pattern that allows the developer to isolate repetitive and often technical code from the business logic. It differs from the normal refactoring towards the single responsibility principle. AOP completely removes the code from the visible code-base to be, and instead configurs and "injects" it at compile-time or execution-time depending on the language. Wikipedia does a good job explaining it in much deeper detail.
AOP是一种编码模式,允许开发人员从业务逻辑中分离出重复的,通常是技术性的代码。 它不同于针对单一责任原则的常规重构。 AOP完全从可见的代码库中删除了代码,而是根据语言在编译时或执行时对其进行配置和“注入”。 维基百科很好地解释了它的细节。
一个很好的例子? (One good example?)
异常处理和日志记录就是一个很好的例子。All applications have their own way of handling exceptions, and the complexity greatly depends on the number of systems and modules integrated.
所有应用程序都有自己的异常处理方式,其复杂性很大程度上取决于集成的系统和模块的数量。
On a SOAP service, for instance, you might end up with a nasty list of try/catch(es) in order to be able to log the exceptions in different categories (Technical, Business, Unhandled) and you need to repeat this logic for every service method. On top of that, it will pollute enormously the code without adding any business value to it; it's just technical code!
例如,在SOAP服务上,您可能会得到一个麻烦的try / catch列表,以便能够记录不同类别(技术,业务,未处理)中的异常,并且您需要重复此逻辑以用于每种服务方法。 最重要的是,它将极大地污染代码,而不会增加任何商业价值。 这只是技术代码!
Take this example:
举个例子:
public void DoSomething()
{
try
{
// do whatever you need to do
}
catch (BusinessException ex)
{
// log this with a lower severity
// create the message to be logged
// concat the stack trace or whatever good way to document the error
// call your logging tool of choice /SemanticLogging, Log4Net, NLog, ...)
}
catch (TechnicalException ex)
{
// log this with a higher severity
// create the message to be logged
// concat the stack trace or whatever good way to document the error
// call your logging tool of choice /SemanticLogging, Log4Net, NLog, ...)
}
catch (Exception ex)
{
// make all hell brake loose!
// create the message to be logged
// concat the stack trace or whatever good way to document the error
// call your logging tool of choice /SemanticLogging, Log4Net, NLog, ...)
}
}
使其干燥 (Making it DRY)
DRY代表Don't
别
Repeat
[R EPEAT
Yourself, and if you look at the above code, you already see a lot of repetition; adding more methods will only make it worse.
是的 ,如果您看一下上面的代码,您已经发现很多重复。 添加更多方法只会使情况变得更糟。
Wouldn't it be nice if you could simply write
如果您可以简单地写,那会不会很好
public void DoSomething()
{
// do whatever you need to do
}
PostSharp进行救援 (
PostSharp to the rescue)
PostSharp是一个免费工具,可在.Net Framework上实现AOP。 “免费”是指免费,就像免费啤酒一样。 尽管它们具有商业版本,但Express版本具有完整的功能,受支持并且是其商业产品的基础。 您也可以将其用于商业目的等等。 我建议阅读他们的常见问题解答并比较他们的版本。
With PostSharp we can have something like:
借助PostSharp,我们可以提供以下内容:
[MyExceptionHandler]
public void DoSomething()
{
// do whatever you need to do
}
[MyExceptionHandler]
public class MyClass
{
public void DoSomething()
{
// do whatever you need to do
}
}
()
But what is that
那是什么
MyExceptionHandler attribute? It's a custom attribute that looks like this: MyExceptionHandler属性? 这是一个自定义属性,如下所示:[Serializable]
public class MyExceptionHandlerAttribute : OnExceptionAspect
{
public MyExceptionHandlerAttribute (){ }
public override void OnException(MethodExecutionArgs args)
{
if (args.Exception.GetType().Equals(typeof(BusinessException)))
{
if (args.Exception.InnerException == null)
MyEventSource.Log.BusinessError(args.Exception.Message);
else
{
var message = args.Exception.Message;
var extraInfo = args.Exception.InnerException.ToString();
MyEventSource.Log.BusinessError(message, extraInfo);
}
}
else if (args.Exception.GetType().Equals(typeof(TechnicalException)))
{
var message = args.Exception.Message;
var extraInfo = args.Exception.InnerException?.ToString();
var stackTrace = args.Exception.StackTrace;
MyEventSource.Log.TechnicalError(message, extraInfo, stackTrace);
}
else
{
var message = args.Exception.Message;
var extraInfo = args.Exception.InnerException?.Message;
MyEventSource.Log.UnhandledError(message, extraInfo);
}
/*
USE THIS IF YOU DON'T WANT TO RETHROW THE EXCEPTION.
LIKE THIS YOU LOG THE ERROR AND THE APPLICATION WON'T COMPLAIN.
IF THIS IS FOR A WEB APP, YOU CAN CONSIDER NOTIFYING THE USER OR
REDIRECTING TO AN ERROR PAGE */
args.FlowBehavior = FlowBehavior.Continue;
}
}
OnExceptionAspect方面 (The OnExceptionAspect aspect)
OnExceptionAspect告诉PostSharp在幕后发挥其魔力,而且非常重要的是,at compile time. PostSharp will wrap the contents of the method that has this attribute with a try/catch block, so this has nothing to do with runtime Reflection and won't impact the performance of your application.
在编译时 。 PostSharp将使用try / catch块包装具有此属性的方法的内容,因此与运行时反射无关,并且不会影响应用程序的性能。
OnExceptionAspect has only one method to override that is the OnException:
OnExceptionAspect只有一种方法可以重写,即OnException:
public override void OnException(MethodExecutionArgs args)
{
// handle the exception
}
MethodExecutionArgs, has all the information you need in order to decide what to do with the exception. Have a look at the documentation for a complete reference.
MethodExecutionArgs,具有您需要的所有信息,以便决定如何处理异常。 请参阅文档以获取完整参考。
()
You might also wonder what's that
您可能还想知道那是什么
MyEventSource there, right? At that point, it really depends on what kind of logging mechanism you want to use. Personally, I like SemanticLogging, but Log4Net and NLog are also really good options. The logging tool implementation itself, as it can be anything you want, is out of the scope of this article. I might write about them in separate articles. MyEventSource在那里,对吗? 那时,它实际上取决于您要使用哪种日志记录机制。 就个人而言,我喜欢SemanticLogging,但是Log4Net和NLog也是非常好的选择。 日志工具实现本身(可能是您想要的任何东西)不在本文的讨论范围之内。 我可能会在单独的文章中写它们。So my implementation, for SemanticLogging, is the following:
因此,对于SemanticLogging,我的实现如下:
[EventSource(Name = "MyApp")]
public class MyEventSource : EventSource
{
public class Keywords
{
public const EventKeywords Page = (EventKeywords)1;
public const EventKeywords DataBase = (EventKeywords)2;
public const EventKeywords Diagnostic = (EventKeywords)4;
public const EventKeywords Perf = (EventKeywords)8;
}
public class Tasks
{
public const EventTask Page = (EventTask)1;
public const EventTask DBQuery = (EventTask)2;
}
private static MyEventSource _log = new MyEventSource();
private MyEventSource() { }
public static MyEventSource Log { get { return _log; } }
[Event(500, Message = "Unhandled Error: {0}. Extra Info: {1}", Level = EventLevel.Critical, Keywords = Keywords.Diagnostic)]
internal void UnhandledError(string message, string extraInfo)
{
if (this.IsEnabled())
this.WriteEvent(500, message ?? "", extraInfo ?? "");
}
[Event(501, Message = "Application Technical Error: {0}. Extra Info: {1}. StackTrace: {2}", Level = EventLevel.Critical, Keywords = Keywords.Diagnostic)]
internal void TechnicalError(string message, string extraInfo, string stackTrace)
{
if (this.IsEnabled())
this.WriteEvent(501, message ?? "", extraInfo ?? "", stackTrace ?? "");
}
[Event(400, Message = "Application Business Error: {0}. Extra Info: {1}", Level = EventLevel.Critical, Keywords = Keywords.Diagnostic)]
internal void BusinessError(string message, string extraInfo = null)
{
if (this.IsEnabled())
this.WriteEvent(400, message ?? "", extraInfo ?? "");
}
[Event(200, Message = "{0}", Level = EventLevel.Informational)]
public void Information(string message)
{
if (this.IsEnabled()) this.WriteEvent(200, message ?? "");
}
}
你还能做什么? (What else can you do?)
好的,到此为止您已经有了AOP的想法,OnExceptionAspect只是PostSharp支持的许多方面之一。 PostSharp文档所做的工作非常出色,不仅描述了PostSharp本身,而且还描述了整个AOP概念。Make sure you have a good look at it: Documentation.
确保您对它有一个很好的了解:文档。
翻译自: https://www.experts-exchange.com/articles/24979/DRY-Exception-Handling-with-PostSharp.html
postsharp