Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

MBG Extensions Library

4.83/5 (21 votes)
16 May 2018CPOL8 min read 60.5K  
Introducing the MBG Extensions Library

Update: 2018-05-16

Well, I can't believe it's been 8 years since I released these extensions! Since CodePlex has been discontinued, I have moved the code to GitHub. In Addition, I'd like to note that I now have a new library for .NET Core called Extenso, which has most of the core extenstions found here as well as some new featurs, such as my generic repository interface and base class, as well as a GenericODataController. Check it out on GitHub with a demo project to showcase the GenericODataController. I will be writing a new article for the Extenso library when I find the time, but for now, this little update will have to suffice. Enjoy!

Introduction

The purpose of this article is to demonstrate the usefulness of extension methods in the .NET framework and particularly the MBG Extensions Library at Codeplex (http://extensionslib.codeplex.com/).

There are quite a few free extension libraries out there, so why another one? Well, for me most of what was in the others I did not find very applicable to my own projects and I wanted to create something that would be reuseable across all my apps and wouldn't leave many methods feeling out of place in the API of most of my apps.

Using the Code

Reference the MBG.Extensions DLL and then add some using statements for the namespaces you'd like to import. I will not go through each of the many extensions; that is something I will leave up to the reader. It is my intention to simply demonstrate some of the most useful ones here.

In()

This method resides in MBG.Extensions.Core and is overloaded. So, how can this method help? Well, first we should look at some common development annoyances and then demonstrate the method to see just how useful it really is.

Here is a common thing we find ourselves doing as developers:

C#
if (myString == "val1" ||
   myString == "val2" ||
   myString == "val3" ||
   myString == "val4" ||
   myString == "val5")
   {
      //Do something
   }

Surely, I'm not the only one who feels this is really nasty and wished for a better way. Well, read on friend! With the In() method, you simply do this:

C#
if (myString.In("val1", "val2", "val3", "val4", "val5"))
{
   //Do something
}

Wow, isn't that so much cleaner?!?

Now suppose that in fact you have an enumerable, perhaps a List<string> and you want to know if a value is in there. Here's how one would normally do it:

C#
bool found = false;
foreach (string s in myList)
{
   if (myString == s)
   {
      found = true;
      break;
   }
}

if (found)
{
   //Do something
}

Now check this out:

C#
if (myString.In(myList))
{
   //Do something
}

I know what you're thinking; dude, that's so cool! Yes, it has been a great help to me and here's something for those who may not quite have realised it yet: This can be used for ANY object type; strings, ints, enums, your own objects...

Let's say you have an enum like so:

C#
public enum MyEnum
{
   MyValue1,
   MyValue2,
   MyValue3,
   MyValue4,
   MyValue5
}

Now you can do this:

C#
MyEnum myEnum = MyEnum.MyValue1;
if (myEnum.In(MyEnum.MyValue2, MyEnum.MyValue3, MyEnum.MyValue5))
{
   //Do Something
}

Enjoy!

So, what's next in the bag of tricks? Well, I'm glad you asked! Ever get tired of writing methods to serialize and deserialize your objects to XML? Well, the more savvy would already have created their own generic methods for this, but with extension methods we can take this a little further. So, without further ado, let's introduce these methods now, shall we?

XmlSerialize() and XmlDeserialize()

The XmlSerialize methods reside in ObjectExtensions and the XmlDeserialize methods are in StringExtensions and FileInfoExtensions.

So, say we have an object called Employees. We can serialize to file like so:

C#
employees.XmlSerialize("C:\\employees.xml");

and deserialize like so:

C#
FileInfo file = new FileInfo("C:\\employees.xml");
Employees employees = file.XmlDeserialize<Employees>();

or we might not want to serialize to file, so we could always use the overloads. Let's try this:

C#
string xml = employees.XmlSerialize();
Employees employees = xml.XmlDeserialize<Employees>();

And here's a tip: Because of these methods, you can very easily add Load and Save classes to your custom objects like so:

C#
public class EmployeeDetails
{
   public static EmployeeDetails Load(string fileName)
   {
      FileInfo fileInfo = new FileInfo(fileName);
      return fileInfo.XmlDeserialize<EmployeeDetails>();
   }
   public void Save(string fileName)
   {
      this.XmlSerialize(fileName);
   }
}

Yay!!! Show me more! Okay, calm down...

Repeat()

Ever find yourself doing something like this...?

C#
string separatorLine = "------------------------------------------";

Well, now you can save some time! How? Like this:

C#
string separatorLine = '-'.Repeat(30);

There's also another Repeat method on the StringExtensions class as well, but it is not used quite as often and the method is the same. I'll leave that to you go explore.

IsMultipleOf()

Instead of this:

C#
int i = 234;
if (i % 10 == 0){ }

We can now do this:

C#
if (i.IsMultipleOf(10)){}

So much cleaner, right? If you're a tidy freak like me, you'll like that one too.

DataColumnCollection.AddRange()

Hey, how many times do you guys find yourselves copying and pasting when creating columns for a DataTable? You normally end up with something like this:

C#
table.Columns.Add("col1");
table.Columns.Add("col2");
table.Columns.Add("col3");

or:

C#
table.Columns.Add(new DataColumn("col1", typeof(string)));
table.Columns.Add(new DataColumn("col2", typeof(bool)));
table.Columns.Add(new DataColumn("col3", typeof(int)));

Well, new extensions let you do this instead:

C#
table.Columns.AddRange("col1", "col2", "col3");

or:

C#
table.Columns.AddRange(
   new DataColumn("col1", typeof(string)),
   new DataColumn("col2", typeof(bool)),
   new DataColumn("col3", typeof(int)));

ToCsv()

The best way to explain this one is just to show you! Try this:

C#
myDataTable.ToCsv("C:\\csvTest.csv");

Ta da! Now you have a CSV file saved to disk. That simple!

DeepClone()

As the name suggests, this method will create a deep clone of your object. However, your object must implement ISerializable for this to even show up in intellisense. In the future, I will look at doing this by reflection instead. Perhaps it can be improved and expanded to all objects.

GetAvailableSqlServers()

This will return a list of all SQL Servers available on your network. Ever wished to use a ComboBox on your connection forms where there is now a TextBox? Well, now you can use a ComboBox and basically populate it with the list returned from this method, like so:

C#
cmbServer.Items.AddRange
    (System.Data.Sql.SqlDataSourceEnumerator.Instance.GetAvailableSqlServers());

Miscellaneous SQL Client Methods

How many times have you had to write code to get a list of databases or tables from a SQL database? I got pretty tired of that after about the 999th time! So what did I do? I wrote the following extensions methods. Note that they are all on the SqlConnection object.

GET DATABASE NAMES:

C#
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
   cmbDatabase.Items.AddRange(connection.GetDatabaseNames());
}

GET TABLE NAMES:

C#
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
   lbTables.Items.AddRange(connection.GetTableNames());
}

OTHER

Note that GetTableNames() is overloaded so that you can provide a database name. Here, we just use the database from the connection string.

GetForeignKeyData() and GetColumnData() will provide you with details about the foreign key relationships and table schema. See the screenshot below for an example using the Northwind database.

MBGExtensionsLibrary/Untitled.png

Compression & Encryption

You will find some interesting methods on the FileInfo class. Not only is there the aforementioned XmlDeserialize<t></t> and BinaryDeserialize<t>, but here you can also find the following extensions:

  • DeflateCompress
  • DeflateDecompress
  • GZipCompress
  • GZipDecompress
  • TripleDESEncrypt
  • TripleDESDecrypt

The encryption methods may not be exactly the way you'd like them implemented, but they do the trick. and you are most welcome to modify the methods in any way you see fit. ;-)

Web Browser: GetScreenshot / SaveScreenshot

These extensions are for the WinForms WebBrowser control. GetScreenshot will return a Bitmap object and SaveScreenshot will save the generated Bitmap directly to disk. Please note that currently this does not work for all sites; especially SharePoint sites. I am no web expert (desktop development is my game), but I am guessing it has something to do with different "frames" or something. I racked my brain for ages trying to figure this one out. if anyone manages a solution, I will be eternally grateful and give full credit to him/her for it.

Other

Amongst others, there are extensions like:

C#
IEnumerable<Person> myList = GetMyListData();
DataTable table = myList.ToDataTable();
C#
Uri url = new Uri("http://www.codeproject.com");
if (url.Ping() == IPStatus.Success)
{
   // Do something
}

// or:

IPAdress ip = IPAdress.Parse("127.0.0.1");
if (ip.Ping() == IPStatus.Success)
{
   // Do something
}
C#
string mySentence = "lower case";
string myPascalSentence = mySentence.ToPascal();
string myNonPascalSentence = myPascalSentence.SpacePascal();
//The above will still be in Title Case however

Conclusion

Yes, extension methods are really helpful but they can also be very annoying when some people just bolt new stuff on willy nilly. My approach is to find what can benefit across multiple projects and try stick with those. Any time you find yourself doing something repetitive, there's a chance to ask yourself, is there a more efficient and/or elegant way to do this? Can I use an extension method to save time? If yes, the next question is; can I use this across multiple projects or will it look really out of place on most other projects? If you think it is reuseable, do your bit and share. Save all of us some time! Have fun guys!

History

Version 1.1, Released Oct 16, 2010

Many new extensions in this release.

  • Core.ByteExtensions
    • BinaryDeserialize
  • Core.ObjectExtensions
    • BinarySerialize (overloaded)
    • DeepClone
  • Data.Sql.SqlDataSourceEnumeratorExtensions
    • GetAvailableSqlServers
  • Data.SqlClient.SqlConnectionExtensions
    • CreateColumn
    • CreateTable
    • GetDatabaseNames
    • GetForeignKeyData
    • GetTableNames (overloaded)
    • GetColumnData
  • IO.FileInfoExtensions
    • BinaryDeserialize
    • GetFileBytes
  • Xml.StringExtensions
    • WrapInCDATA

See SqlDemo project for a treat! Enjoy!

============================================================

Version 1.2, Released Oct 28, 2010

  • [MBG.Extensions]
    Core.ByteExtensions
    • RSAEncrypt
    • RSADecrypt
    • TripleDESDecrypt
  • Core.EnumExtensions
    • Parse
  • Core.EnumerableExtensions
    • ContainsAny (Moved From ObjectExtensions to here, where it should have been)
    • ToDataTable
  • Core.ObjectExtensions
    • InvokeMethod
    • InvokeExtensionMethod
    • ParseOrDefault
    • TryParseOrDefault
  • Core.StringExtensions
    • ToPascal
    • TripleDESEncrypt
  • Core.UriExtensions
    • Ping (overloaded)
  • IO.FileInfoExtensions
    • DeflateCompress
    • DeflateDecompress
    • GZipCompress
    • GzipDecompress
    • TripleDESEncrypt
    • TripleDESDecrypt
  • Net.IPAddressExtensions
    • Ping (overloaded)
  • Reflection.TypeExtensions
    • GetExtensionMethod (overloaded)
    • GetExtensionMethods
  • Xml.XmlAttributeExtensions
    • Exists
    • GetValueOrSpecified
  • [MBG.Extensions.WinForms]
    HtmlDocumentExtensions
    • DoPostback (overloaded)
    • GetElementByTitle
  • WebBrowserExtensions
    • GetScreenshot (overloaded)*
    • SaveScreenshot (overloaded)*

*Note: Screenshots are not working for every site. SharePoint sites for example are particularly troublesome. I think it may have something to do with different "frames" or something. If anyone can fix this, I would really appreciate it and give full credit to that person.

============================================================

Version 1.3, Released Dec 06, 2010

  • [MBG.Extensions]
  • Collections.CollectionExtensions
    • AddIfNew
    • RemoveRange (Moved From ListExtensions to here, where it should have been)
  • Collections.EnumerableExtensions
    • ToCommaSeparatedList has been replaced by:Join() and ToValueSeparatedList
      • Join is for a single line of values.
      • ToValueSeparatedList is generally for collection and will separate each entity in the collection by a new line character
    • ToQueue
    • ToStack
  • Core.ByteExtensions
    • TripleDESDecrypt
  • Core.DateTimeExtensions
    • ToISO8601DateString
  • Core.StringExtensions
    • AddDoubleQuotes
    • AddSingleQuotes
    • Append is now overloaded
    • Between
    • IsNullOrWhitespace
    • IsPlural
    • LeftOf (overloaded)
    • LeftOfLastIndexOf
    • Pluralize
    • Prepend is now overloaded
    • RightOf (overloaded)
    • RightOfLastIndexOf
    • Singularize
  • Data.DataColumnExtensions
    • ChangeDataType
  • Data.SqlClient.SqlConnectionExtensions
    • CreateColumn (Fixed bug with Unique Identifier columns)
    • CreateTable (Made some small changes and added an overload)
    • Insert (overloaded)
    • InsertCollection (overloaded)
  • IO.FileInfoExtensions
    • GetBytes (Renamed From GetFileBytes and added overload)
    • TripleDESEncrypt & TripleDESDecrypt now not only return the encrypted / decrypted data, but actually Encrypt / decrypt the file as well, as one would expect
  • IO.StreamExtensions
    • DeflateCompress
    • DeflateDecompress
    • GZipCompress
    • GZipDecompress
  • Reflection.ObjectExtensions
    • GetPrivateFieldValue
    • GetPrivatePropertyValue
    • GetPropertyValue (overloaded)
    • HasProperty
    • InvokeMethod (Moved from Core.ObjectExtensions to here)
    • InvokeExtensionMethod (Moved from Core.ObjectExtensions to here)
    • SetPrivateFieldValue
    • SetPrivatePropertyValue
    • SetPropertyValue (overloaded)
  • Reflection.StringExtensions
    • ParseOrDefault (Moved from Core.ObjectExtensions to here)
    • TryParseOrDefault (Moved from Core.ObjectExtensions to here)
  • Reflection.TypeExtensions
    • GetDefaultValue
    • IsCollection
  • Security.PrincipalExtensions
    • GetRoles
  • ServiceProcess.ServiceControllerExtensions
    • Restart
  • Text.StringBuilderExtensions
    • Append() overloads: "params string[]", "params T[]" and "IEnumerable<T>"
  • [MBG.Extensions.WinForms]
  • RichTextBoxExtensions
    • Highlight (overloaded)
    • HighlightAll (overloaded)
  • [MBG.Extensions.WPF]
  • DependencyObjectExtensions
    • GetChildren

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)