Image Image Image Image Image
Scroll to Top

To Top

AOP Aspect-oriented programming (AOP) is a pragmatic passion that I document here.

xCutting – AOP bei der .NET User Group Niederrhein – Video, Slides & Download

On 12, Apr 2012 | inAOP, Clean Code Developer | vonJohannes Hoppe

Johannes Hoppe spricht von seiner Sicht über Clean-Code und die Grenzen von objektorientierter Programmierung bei der .NET User Group Niederrhein. Anhand praktischer Bespiele zeigt er, wie man mit dem AOP-Framework Postsharp elegante Modularisierungsansätze erhält. Der Vortrag richtet sich an interessierte Einsteiger in das Thema Aspektorientierte Programmierung (AOP) mit .NET.

Alle relevanten Code-Fragmente sind weiter unten aufgelistet!

  1. ActionResult Edit
  2. MyConvertExeption
  3. LogTimeAspect
  4. SimpleCacheBaseAspect


Hier sind alle Code-Fragmente aus dem Video:

ActionResult Edit

[HandleError(ExceptionType = typeof(MyException))]
[AcceptVerbs(HttpVerbs.Post)]
[MyConvertExeption]
public ActionResult Edit(Note noteToEdit, int[] newCategories)
{
    NoteWithCategories changedNote = this.WebNoteService.Update(noteToEdit, newCategories);
    return View(changedNote);
}


MyConvertExeption

using PostSharp.Aspects;
 
[Serializable]
public class MyConvertExeption : OnExceptionAspect
{
    public override void OnException(MethodExecutionArgs args)
    {
        throw new MyException("Fehler", args.Exception);
    }
}

LogTimeAspect

namespace PostsharpAspects.Logging
{
    using System;
    using System.Diagnostics;
    using System.Reflection;
 
    using NLog;
 
    using PostSharp.Aspects;
    using PostSharp.Aspects.Dependencies;
 
    [Serializable]
    [ProvideAspectRole(StandardRoles.PerformanceInstrumentation)]
    [AspectRoleDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, StandardRoles.Caching)]
    [AspectRoleDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, StandardRoles.ExceptionHandling)]
    [AspectRoleDependency(AspectDependencyAction.Commute, StandardRoles.PerformanceInstrumentation)]
    public class LogTimeAspect : OnMethodBoundaryAspect
    {
        private const int SlowTotalMilliseconds = 250;
 
        private static readonly Logger Logger = LogManager.GetLogger("LogTimeAspect");
        private static readonly Stopwatch Stopwatch = new Stopwatch();
        private string instanceName;
 
        static LogTimeAspect()
        {
            Stopwatch.Start();
        }
 
        /// <summary>
        /// Method executed at build time.
        /// </summary>
        public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
        {
            this.instanceName = method.DeclaringType.FullName + "." + method.Name;
        }
 
        /// <summary>
        /// Saves the time method start
        /// </summary>
        [DebuggerStepThrough]
        public override void OnEntry(MethodExecutionArgs args)
        {
            args.MethodExecutionTag = Stopwatch.ElapsedTicks;
        }
 
        /// <summary>
        /// Stops the time on method end
        /// </summary>
        [DebuggerStepThrough]
        public override void OnExit(MethodExecutionArgs args)
        {
            long timeInTicks = Stopwatch.ElapsedTicks - (long)args.MethodExecutionTag;
            double totalMilliseconds = TimeSpan.FromTicks(timeInTicks).TotalMilliseconds;
 
            if (totalMilliseconds > SlowTotalMilliseconds)
            {
                Logger.Trace(String.Format("{0}ms\t- {1}", totalMilliseconds, this.instanceName));
            }
 
            base.OnExit(args);
        }
    }
}

SimpleCacheBaseAspect

namespace PostsharpAspects.Caching
{
    using System;
    using System.Reflection;
    using System.Text;
 
    using PostSharp.Aspects;
 
    using PostsharpAspects.Caching.CacheImplementation;
 
    [Serializable]
    public class SimpleCacheBaseAspect : OnMethodBoundaryAspect
    {
        protected ICache Cache { get; set; }
 
        public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
        {
            string prefix = method.DeclaringType.ToString();
            this.Cache = new Cache(prefix);
        }
 
        public override void OnEntry(MethodExecutionArgs args)
        {
            string cacheKey = GenerateCacheKey(args);
            object value = this.Cache.Get(cacheKey);
 
            if (value == null)
            {
                args.MethodExecutionTag = cacheKey;
                return;
            }
 
            args.ReturnValue = value;
            args.FlowBehavior = FlowBehavior.Return;
        }
 
        public override void OnSuccess(MethodExecutionArgs args)
        {
            string cacheKey = (string)args.MethodExecutionTag;
            this.Cache.Insert(cacheKey, args.ReturnValue);
        }
 
        protected static string GenerateCacheKey(MethodExecutionArgs args)
        {
            StringBuilder stringBuilder = new StringBuilder();
 
            for (int i = 0; i < args.Arguments.Count; i++)
            {
                if (i > 0)
                {
                    stringBuilder.Append("|");
                }
 
                stringBuilder.AppendFormat(
                    "{0}_{1}",
                    args.Method.GetParameters()[i].Name,
                    args.Arguments.GetArgument(i) ?? "null");
            }
 
            return stringBuilder.ToString();
        }
    }
}

Tags | ,