 When I last consulted one company, we discussed an internal SOA framework that should interact with the enterprise databases. This framework was SOA only by name, completely homegrown, and what is most sad, it was a “favorite project” of the head of the IT department. It was not secure and built on dubious technologies and solutions. In general, it was made to solve some problem, which either does not exist or it could not be solved by simple means. My team was extremely disappointed with the structure of this framework. But, as a consultant, it is very often necessary first to think over ways to solve the problem, it is impossible to tell the customer that his product is “bad”, you must first build his trust in yourself, and only then solve more serious problems. One way or another, such a process can take years, and everything depends on the company in which such changes will take place. Then I thought about using aspect-oriented framework to solve this problem.
 When I last consulted one company, we discussed an internal SOA framework that should interact with the enterprise databases. This framework was SOA only by name, completely homegrown, and what is most sad, it was a “favorite project” of the head of the IT department. It was not secure and built on dubious technologies and solutions. In general, it was made to solve some problem, which either does not exist or it could not be solved by simple means. My team was extremely disappointed with the structure of this framework. But, as a consultant, it is very often necessary first to think over ways to solve the problem, it is impossible to tell the customer that his product is “bad”, you must first build his trust in yourself, and only then solve more serious problems. One way or another, such a process can take years, and everything depends on the company in which such changes will take place. Then I thought about using aspect-oriented framework to solve this problem. 
All source codes of the given programs are available at the link: GitHub
[Serializable] public class TransactionScopeAttribute : OnMethodBoundaryAspect { [NonSerialized] private ICharityService _charityService; private string _methodName; private string _className; public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) { _className = method.DeclaringType.Name; _methodName = method.Name; } public override void RuntimeInitialize(System.Reflection.MethodBase method) { // in practice, the begin/rollback/commit might be in a more general service // but for convenience in this demo, they reside in CharityService alongside // the normal repository methods _charityService = new CharityService(); } public override void OnEntry(MethodExecutionArgs args) { _charityService.BeginTransaction(); } public override void OnException(MethodExecutionArgs args) { _charityService.RollbackTransaction(); var logMsg = string.Format("exception in {0}.{1}", _className, _methodName); // do some logging } public override void OnSuccess(MethodExecutionArgs args) { _charityService.CommitTransaction(); } }  [Serializable] public class TransactionScopeAttribute : MethodInterceptionAspect { [NonSerialized] private ICharityService _charityService; [NonSerialized] private ILogService _logService; private int _maxRetries; private string _methodName; private string _className; public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) { _methodName = method.Name; _className = method.DeclaringType.Name; } public override void RuntimeInitialize(System.Reflection.MethodBase method) { _charityService = new CharityService(); _logService = new LogService(); _maxRetries = 4; // you could load this from XML instead } public override void OnInvoke(MethodInterceptionArgs args) { var retries = 1; while (retries <= _maxRetries) { try { _charityService.BeginTransaction(); args.Proceed(); _charityService.CommitTransaction(); break; } catch (DataException) { _charityService.RollbackTransaction(); if (retries <= _maxRetries) { _logService.AddLogMessage(string.Format( "[{3}] Retry #{2} in {0}.{1}", _methodName, _className, retries, DateTime.Now)); retries++; } else { _logService.AddLogMessage(string.Format( "[{2}] Max retries exceeded in {0}.{1}", _methodName, _className, DateTime.Now)); _logService.AddLogMessage("-------------------"); throw; } } catch (Exception ex) { _charityService.RollbackTransaction(); _logService.AddLogMessage(string.Format( "[{3}] {2} in {0}.{1}", _methodName, _className, ex.GetType().Name, DateTime.Now)); _logService.AddLogMessage("-------------------"); throw; } } _logService.AddLogMessage("-------------------"); } } 
Source: https://habr.com/ru/post/126624/
All Articles