.Net Tips – Restricting attribute usage to specific type

Before you get your hopes up, sorry, there’s no built-in support to allow you to restrict the usage of your attribute to a type easily. That’s not to say that it’s impossible though!

If you’re reading this, I assume that you’ve tried to write a custom attribute yourself and realised that the options available in the AttributeTargets enum is fairly limited.

For those of you who are familiar with PostSharp, you would probably have noticed that one of the methods you can override is curiously called CompileTimeValidate and returns a boolean value. You can use the MethodBase argument passed into this method to inspect the type the attribute has been applied to and perform some validation logic there, e.g.:

[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method)]
public class MyAttribute : OnMethodBoundaryAspect
{
    public override bool CompileTimeValidate(System.Reflection.MethodBase method)
    {
        var type = method.DeclaringType;

        // if the attribute is used outside the Service class, fail the build
        if (!type.Equals(typeof(Service)))
        {
            throw new Exception("MyAttribute can only be used in the Service class");
        }

        return true;
    }
}

Because you have the metadata for the method in hand, there’s nothing to stop you from restricting the usage of your attribute by input and return types too, e.g. attribute can only be applied to a method which returns string, etc.

If this is too much work for your liking, Marc Gravell blogged about a neat trick you could do to achieve the same effect here. The trick exploits the protected modifier in C# so that an attribute declared in the base type can be used by derived types but not by others. Here’s the code snippet from his original post:

abstract class MyBase
{
    [AttributeUsage(AttributeTargets.Property)]
    protected sealed class SpecialAttribute : Attribute {}
}

class ShouldBeValid : MyBase
{
    [Special] // works fine
    public int Foo { get; set; }
}

class ShouldBeInvalid
{
    // not a subclass of MyBase
    [Special] // type or namespace not found
    [MyBase.Special] // inaccessible due to protection level
    public int Bar{ get; set; }
}

Update: I saw another related question on StackOverflow here, as far as I’m aware you won’t be able to do this without the help of PostSharp as you won’t have access to the access modifiers (public, protected, internal or private) that was applied to the field when it was declared. With PostSharp however, this is how you would could go about doing such validation at compile time and make sure the attribute is applied to a public or protected field:

[Serializable]
[AttributeUsage(AttributeTargets.Field)]
public class MyAttribute : OnFieldAccessAspect
{
    public override bool CompileTimeValidate(System.Reflection.FieldInfo field)
    {
        if (field.IsPublic || field.IsFamily)
        {
            throw new Exception("Attribute can only be applied to Public or Protected fields");
        }

        return true;
    }
}

AOP – FIFO Memoizer with PostSharp

Back in my first post on AOP, I mentioned the Memoizer on D. Patrick Caldwell’s blog, well, today I came across a situation where I was able to use it but first I needed to make a few modifications because the original implementation didn’t satisfy some of my requirements:

  • There is no cap on the size of the dictionary, I want to avoid a situations where my application uses too much memory, and in the extreme case throws a OutOfMemoryException;
  • There is one static cache shared across all methods, so even with a cap on the size of the dictionary it won’t stop one method from taking up all the available spaces in the dictionary
  • The order of the memos is not kept, so you won’t be able to implement have FIFO strategy for removing old memo entries

In case you’re wondering why I would require these functionalities, I’m building an image viewer with zip support and it doesn’t make sense to load all the images in the zip file into memory at the start (the zip files can be typically hundreds of megs big).

The images are sorted, and as you’re navigating through the images it behaves like a LinkedList anyway, so I’m implementing a sliding window based on where you are in the list and load the previous and next 10 images into cache. Therefore a FIFO memoizer can help reduce the amount of reads from the zip file I need to perform (decompression is an expensive operation).

And here’s the modified version of the Memoizer attribute:

[Serializable]
[AttributeUsage(AttributeTargets.Method)] // only allowed on methods
[DebuggerStepThrough]
public sealed class MemoizeAttribute : OnMethodInvocationAspect
{
    private const int DefaultMemoSize = 100; // default memo size is 100
    // private field to store memos
    private readonly Dictionary<string, object> _memos = new Dictionary<string, object>();
    // private queue to keep track of the order the memos are put in
    private readonly Queue<string> _queue = new Queue<string>();

    #region Constructors
    public MemoizeAttribute() : this(DefaultMemoSize)
    {
    }
    public MemoizeAttribute(int memoSize)
    {
        MemoSize = memoSize;
    }
    #endregion

    public int MemoSize { get; set; } // how many items to keep in the memo

    // intercept the method invocation
    public override void OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        // get the arguments that were passed to the method
        var args = eventArgs.GetArgumentArray();
        var keyBuilder = new StringBuilder();
        // append the hashcode of each arg to the key
        // this limits us to value types (and strings)
        // i need a better way to do this (and preferably
        // a faster one)
        for (var i = 0; i < args.Length; i++)
            keyBuilder.Append(args[i].GetHashCode());
        var key = keyBuilder.ToString();
        // if the key doesn't exist, invoke the original method
        // passing the original arguments and store the result
        if (!_memos.ContainsKey(key))
        {
            _memos[key] = eventArgs.Method.Invoke(eventArgs.Instance, args);
            _queue.Enqueue(key);
            // if we've exceeded the set memo size, then remove the earliest entry
            if (_queue.Count > MemoSize)
            {
                var deQueueKey = _queue.Dequeue();
                _memos.Remove(deQueueKey);
            }
        }
        // return the memo
        eventArgs.ReturnValue = _memos[key];
    }
}

And here’s how you use it, remember, the size cap applies to all the calls to this method (not limited to a particular instance):

[Memoize(5)]
private MemoryStream GetImageStream(ZipFile zipFile, string fileName)
{
    using (var memoryStream = new MemoryStream())
    {
        zipFile[fileName].Extract(memoryStream);
        return memoryStream;
    }
}

AOP – Method execution time watcher with PostSharp

I found a nice usage of AOP the other day, using AOP to keep track of how long your method takes to execute and log a warning message if it takes longer than a threshold you supply. You can configure it to log execution times or only flag warning entries when threshold’s been exceeded.

[Serializable]
[DebuggerStepThrough]
[AttributeUsage(AttributeTargets.Method)]
public sealed class LogExecutionTimeAttribute : OnMethodInvocationAspect
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(LogExecutionTimeAttribute));

    // If no threshold is provided, then just log the execution time as debug
    public LogExecutionTimeAttribute() : this (int.MaxValue, true)
    {
    }
    // If a threshold is provided, then just flag warnning when threshold's exceeded
    public LogExecutionTimeAttribute(int threshold) : this (threshold, false)
    {
    }
    // Greediest constructor
    public LogExecutionTimeAttribute(int threshold, bool logDebug)
    {
        Threshold = threshold;
        LogDebug = logDebug;
    }

    public int Threshold { get; set; }
    public bool LogDebug { get; set; }

    // Record time spent executing the method
    public override void OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        var start = DateTime.Now;
        eventArgs.Proceed();
        var timeSpent = (DateTime.Now - start).TotalMilliseconds;

        if (LogDebug)
        {
            Log.DebugFormat(
                "Method [{0}{1}] took [{2}] milliseconds to execute",
                eventArgs.Method.DeclaringType.Name,
                eventArgs.Method.Name,
                timeSpent);
        }

        if (timeSpent > Threshold)
        {
            Log.WarnFormat(
                "Method [{0}{1}] was expected to finish within [{2}] milliseconds, but took [{3}] instead!",
                eventArgs.Method.DeclaringType.Name,
                eventArgs.Method.Name,
                Threshold,
                timeSpent);
       }
}

.Net Tips – use DebuggerStepThrough attribute

When debugging your application, don’t you just get annoyed that pressing F11 keep taking you into the get method of the properties (auto-properties excluded!) passed into the method rather than the method you want to step into?

I use auto-properties wherever possible because they’re syntactically cleaner and have less maintenance overhead, and I have the same amount of control as with private fields because I can define the access privilege of the get and set methods independently.

The only time when I will still use a private field is when I want to expose a readonly variable so I can confine the assignment to the constructor but still allow other classes to access it. 99.9% of the time the get method will do a straight return so stepping through it have no benefit whatsoever, and it’s times like this the DebuggerStepThrough attribute can be a timesaver:

private int _myIntField;
public int MyIntProperty
{
    [DebuggerStepThrough]
    get { return _myIntField; }
}

This will stop the debugger from stepping into the get method when you try to step into a method like this:

DoSomething(obj.MyIntProperty);

You can, however, still put a break point against the get method when you do want to step through it without having to first take off the attribute and recompile though! :-D

Another situation where the DebuggerStepThrough attribute can save you time is when you use PostSharp-powered attributes.

When you’re debugging through some code which has try-catch logic encapsulated in a OnMethodInvocationAspect attribute like the RetryOnSqlDeadLockOrConnectionTimeOutExceptionAttribute I have here, you might be taken into attribute class when all you care about is what’s happening in the method the attribute is applied to.

Buzzword Buster – AOP

Definition:

Aspect Oriented Programming (AOP) is a programming paradigm where each application can focus on its primary functions and core concerns by encouraging greater modularity and increasing separation of cross-cutting concerns (such as logging and authentication).

Purpose:

In any real-world applications, when you’re writing code to address the problem domain (say, booking an order) you might need to address other concerns such as:

  • persistence – writing to the database for example
  • transaction handling – defining transaction scope and setting rollback strategy, etc.
  • security – user authentication for example
  • logging – for auditing and debugging

So effectively you’re mixing multiple domains with fine-grained intersections and likely to end up with:

  • tangled code – making it more difficult to work out what the code is doing to address the core concern
  • boilerplate code at every intersection point – introducing duplicated code and increasing the size of the code base and the blast radius of any change that are not related to the problem domain, e.g. changing the persistence media..

AOP aims to address these problems by separating cross-cutting concerns into single units called aspects, each aspect encapsulates behaviours that affect multiple classes into reusable modules.

Parting thoughts..

As far as I can think of, the only drawback of AOP is that you no longer see all the behaviours of your class when you open it and it requires knowledge of the whole system to know what else are happening under the cover. Which interestingly, is the flip side of the same coin because you employ AOP when you don’t want to deal with cross-cutting concerns all the time!

One of the ways to mitigate this problem is to build up a culture in your team and standardise how AOP is implemented so that everyone is on the same page and there are few surprises.

Frameworks:

PostSharp provides a lightweight AOP framework for the .Net platform and is establishing itself as the de facto standard much like the way AspectJ has done for Java.