In-Class AOP | Using Action<T> Delegates to Reduce Redundant Code

by Jason Wicker 23. October 2009 14:39

I am a recent fanboy of AOP (aspect oriented) design patterns, so maybe this isn't anything new to you, but MAN it's changed my life. Staying hard-and-fast on the "DRY" principle (don't repeat yourself) is an awesome concept, but it isn't always easy. Take for instance the "Try/Catch/Finally" block. When accessing external resources, you sometimes need to wrap each call in a this block to manage the resource in the event of a failure. Something like, the following:

public void DoSomething()

{

    try

    {

        // Perform the action

        _service.Do();

    }

    catch (Exception exc)

    {

        // Log exception, etc.

        Log(exc);

        _service.Abort();

    }

    finally

    {

        // Clean up resources

        _service.Close();

    }

}

Now it isn't terribly obvious how you can get around this (at least it wasn't for me). If only we could have every call to this service wrapped in the same try/catch/finally block... Enter the Action<T> delegate. With this guy, you can create a method within this class (or a base blass) that provides this block as a wrapper for your action. For instance:

private void Invoke(Action<IService> action)

{

    try

    {

        // Perform the action

        func(_service);

    }

    catch (Exception exc)

    {

        // Log exception, etc.

        Log(exc);

    }

    finally

    {

        // Clean up resources

        _service.Close();

    }

}

Then, you could make your calls like through the "Invoke" method and everything would be wrapped in the common Try/Catch/Finally block. Check it out:

public void DoSomething()

{

    Invoke(s=>

        s.Do()

        );

}

It's that easy! Now, if you are going to be returning values, then you may want to create an overload using the Func<> delegate, like this:

private TReturnType Invoke<TReturnType>(Func<IService, TReturnType> action)

{

    try

    {

        // Perform the action

        return func(_service);

    }

    catch (Exception exc)

    {

        // Log exception, etc.

        Log(exc);

    }

    finally

    {

        // Clean up resources

        _service.Close();

    }

}

Then it could be used like so:

public string DoSomething()

{

    return Invoke(s=>

        s.Do()

        );

}

As you can see, this kind of thinking could have a major impact on your code and increase your code's reusability.

Enjoy.

Tags: , ,

Enum<T> - Better Enum Parsing using Strongly-Typed Generics

by Jason 22. October 2009 13:55

When dealing with Enums (parsing, getting values, etc.) there is entirely too much casting and Types being passed around. For instance, to simply parse a string to it’s Enum value, one would do this:

TestEnum testEnum = (TestEnum)Enum.Parse(typeof(TestEnum), "Super");

We had to define the enum type THREE (count them) THREE times, in a single row. Blech! With this helper, this statement becomes much cleaner:

var testEnum = Enum<TestEnum>.Parse("Super");

Only ONE declaration of the Enum type. Nice! (Okay, so I cheated and used the 'var' keyword, but you get the point)

Also, there are some really handy helpers built-in, like:
 TryParse - four overloads, two returning a bool with an out parameter and two that just returns NULL if it fails to parse.
 ToEnumerable - returns a typed-list of all the Enum options

Example:

// Fails parsing, enum value = null

var enumTest = Enum<TestEnum>.TryParse("WrongValue");

 

// Get an IEnumerable of the Enums

var list = Enum<TestEnum>.ToEnumerable();

Plus more goodies -- feel free to take a look.

Now, I am certain that I am not the first to create a generic helper to make parsing Enums easier (article one, article two to name a few) but here is a complete Enum<T> helper class for all your Enum needs. Note, I even recreated all the standard static methods available in Enum, so that there will be no need to pass the “typeof(X)” parameter.

// So this...

string name = Enum<TestEnum>.GetName(TestEnum.Super);

 

// Instead of this...

string name = Enum.GetName(typeof(TestEnum), TestEnum.Super);

Enum<T> Code:

public static class Enum<T>

    where T: struct

{

    public static T Parse(string name)

    {

        return Parse(name, false);

    }

 

    public static T Parse(string name, bool ignoreCase)

    {

        return (T)Enum.Parse(typeof(T), name, ignoreCase);

    }

 

    public static T? TryParse(string name)

    {

        return TryParse(name, false);

    }

 

    public static T? TryParse(string name, bool ignoreCase)

    {

        T value;

        if (!string.IsNullOrEmpty(name) && TryParse(name, out value, ignoreCase))

            return value;

        return null;

    }

 

    public static bool TryParse(string name, out T value)

    {

        return TryParse(name, out value, false);

    }

 

    public static bool TryParse(string name, out T value, bool ignoreCase)

    {

        try

        {

            value = Parse(name, ignoreCase);

            return true;

        }

        catch (ArgumentException)

        {

            value = default(T);

            return false;

        }

    }

 

    public static IEnumerable<T> ToEnumerable()

    {

        foreach (var value in Enum.GetValues(typeof(T)))

             yield return (T)value;

    }

 

    public static IEnumerable<object> GetValues()

    {

        foreach (var value in Enum.GetValues(typeof(T)))

            yield return value;

    }

 

    public static IDictionary<object, string> GetDictionary()

    {

        Dictionary<object, string> dictionary = new Dictionary<object, string>();

        foreach (var value in GetValues())

            dictionary.Add(

                Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))),

                GetName(value));

 

        return dictionary;

    }

 

    #region Strongly-Typed Enum Extenders

 

    public static string Format(object value, string format)

    {

        return Enum.Format(typeof(T), value, format);

    }

 

    public static string GetName(object value)

    {

        return Enum.GetName(typeof(T), value);

    }

 

    public static IEnumerable<string> GetNames()

    {

        return Enum.GetNames(typeof(T));

    }

 

    public static Type GetUnderlyingType()

    {

        return Enum.GetUnderlyingType(typeof(T));

    }

 

    public static bool IsDefined(object value)

    {

        return Enum.IsDefined(typeof(T), value);

    }

 

    public static T ToObject(object value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(byte value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(sbyte value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(int value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(uint value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(long value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(ulong value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(short value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    public static T ToObject(ushort value)

    {

        return (T)Enum.ToObject(typeof(T), value);

    }

 

    #endregion

}

Enjoy!

Source Code:

Enum.zip (858.00 bytes)

Tags: , ,

Stack Overflow

Month List