Cool stuff in FubuCore No. 2: Extension Methods


This is the second post of the FubuCore series mentioned in the Introduction post.

This post covers the various and plentiful extension methods contained in the FubuCore project. We have built up these extensions methods over the last 3-4 years in anger. Some of them may be a little sloppy and not up to your liking or taste level, but all of them are used heavily and have been running in multiple production systems for quite a while (some of them over 2 years). We find most of them to be invaluable and use them every day. I hope you find some value in them as well.

IfNotNull

Various overloads (Source)

This one is super handy.  How many times have you written code like this?

if( value != null )
{
    doSomething();

}

 

Well, it really stinks when you’re in the middle of a code flow and you need to do something only if “value” is not null. Well, now you can do stuff like this:

var name = employee.IfNotNull(e => e.FullName);
// or
employee.IfNotNull(e => doSomething(e));

 

Hiding Data In Views With If/IfNot

(Source)

With Fubu authorization, you can hide pieces of information in the view if the current ser doesn’t have access to it.  We wrote short-hand methods to assist us with this in the view. Assume the view’s model has a property called “CanSeeSalaryInformation” which represents the result of an authorization check for a user permission.

<span><%= employee.Salary.If(()=> Model.CanSeeSalaryInformation)%></span>

 

Making Dictionary.Get Not As Annoying

Various overloads (Source)

If you do manage to find yourself using a Dictionary instead of a Cache, you can get around some of the pain of having to do the “ContainsKeys” checks by using the Get extension methods. A lot of times you want to get a value from a dictionary but don’t want to do all the “ContainsKey” checking or messing with the “out” variable in the “TryGetValue” method.

Let’s say you want to get the value of a key from a dictionary which may not be there. And if it’s not there, then return a default value (let’s say, empty string).

dictionary.Get("mykey", "");

Enumerable Extensions

(Source)

Like most programmers, we do a lot of stuff with enumerables (lists, arrays, and other fun list-y type structures). So we’ve evolved a lot of enhancements and extensions to make them easier to use in various situation.

IList Extensions

Fill(T value): Add an item to a list if it isn’t already in the list.

RemoveAll(Func<T, bool> whereEvaluator): Removes items from the list that match the function/predicate.

**AddRange(IEnumerable items)**: For some reason, [AddRange](http://msdn.microsoft.com/en-us/library/z883w3dc.aspx) is only on List and not on IList, so we added it to IList.

AddMany(params T[] items): Just like AddRange, but allows for many param arguments as well as method chaining.

IEnumerable Extensions

**Each(Action action)**: Just like “foreach”, but is inline and allows method chaining.

FirstValue(Func<T, UReturn> returnFunc): Kinda like FirstOrDefault, but more like combining a Where and a Select and a FirstOrDefault in one method.  This method will iterate over the enumerable, executing your returnFunc until it gets a non-null result.  If none was found, it just returns null.

**IsEqualTo(IEnumerable expected):** This one we use (almost?) exclusively for testing to ensure the result of some method returns exactly what we expected. It will check the lengths/count of each enumerable and then verify that each item in each list passes a call to “.Equals()”.

String Extensions

Join(string separator): Just like String.Join except it allows method chaining.

Stream Extensions

(Source)

ReadAllText: This does the tedium of new()’ing up a StreamReader and calling ReadToEnd.  It saves a few lines of code when all you want to do is open a stream and read the whole thing in. I think we use this for reading text embedded assembly resources  If you’re working with files, it’s better to just call File.ReadAllText.

String Extensions

(Source)

CombineToPath(string root): If the path is rooted, just returns the path.  Otherwise, this combines the root and path. (Uses Path.IsPathRooted and Path.Combine)

ToFullPath(): Just like Path.GetFullPath, but allows method chaining.

AppendPath(params string[] paths): Repeatedly calls Path.Combine on a list of paths (i.e. /bar/baz/zab/rab).

PathRelativeTo(string root): Makes the current string (assumed to be a path) rooted against the specified root. (i.e. “/bar/baz”.PathRelativeTo(“c:”) will result in “c:/bar/baz”).

IsEmpty(): Same as String.IsNullOrEmpty, but hangs off the string itself as an extension method.

IsNotEmpty(): Opposite of IsEmpty.

**IsNotEmpty(Action action):** Same as IsNotEmpty() but will execute an action if the string is, in fact, not empty. This is useful for keeping statements in-line.

ToBool: Converts a string to boolean. It handles the null/empty check, and then calls Bool.Parse.

ToFormat: (My personal favorite) Calls String.Format, but allows for method chaining. Example:

return "You have {0} turns remaining.".ToFormat(numTurnsLeft);

EqualsIgnoreCase(string otherString): Calls String.Equals with StringComparison.InvariantCultureIgnoreCase.

Capitalize: A more convenient way to call: CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value)

HtmlAttributeEncode, HtmlEncode, HtmlDecode, UrlEncode, UrlDecode: A more convenient way to call the corresponding methods on System.Web.HttpUtility.

ConvertCRLFToBreaks(string plainText): Converts “\r\n” or “\n” to “
” (handy for html-izing some plain text”).

ToDateTime(string dateTimeValue): A more convenient way of calling DateTime.Parse.

ToGmtFormattedDate: Prints out a log-file friendly date/time stamp in full format in the GMT timezone (i.e. “yyyy-MM-dd hh:mm:ss tt GMT”).

ToDelimitedArray: A more convenient way of calling String.Split, plus it strips away extra whitespace so “a  “,”b”, and ”    c” get turned into “a,b,c”.

IsValidNumber: Uses regex to attempt to determine if the string contains something recognizable as a number. If memory serves, this was written in anger at Decimal.Parse which never seemed forgiving enough and would frequently miss values that were clearly (to humans) numbers.

getPathParts: Breaks down a string like “c:/bar/baz/zab” into a list of strings “c:”, “bar”, “baz”, and “zab”.

DirectoryPath: A more convenient way of calling Path.GetDirectoryName.

Type Extensions

(Source)

These are some *really* handy methods if you do a lot of work with generics, expression trees, or both.

Unfortunately, this blog post would be four times larger if I mentioned all the great extension methods.  I strongly suggest you browse through this source file (linked above) because you will definitely find at least one thing that you can use.

I hand-picked a few ones that I thought were especially useful and might whet your appetite :

IsNullableOfT(): Determines if the given type implements Nullable<> or not (i.e. DateTime?).

IsNullableOf(Type otherType): Determines if the given type is a Nullable or not. For example, typeof(DateTime?).IsNullableOf(typeof(DateTime)) would be True.

**IsTypeOrNullableOf**:  Useful for checking if this type is one of DateTime or a DateTime?, for example.

**CanBeCastTo:** This helps to rectify the oft-confusing backward logic of [Type.IsAssignableFrom](http://msdn.microsoft.com/en-us/library/system.type.isassignablefrom.aspx).

IsConcreteWithDefaultCtor: Determines if this type is a concrete type with a default/open constructor (i.e. you could call Activator.CreateInstance() on it with no exceptions).

Cool stuff in FubuCore No. 1: Cache