Thursday, November 19, 2009

LINQing to MEF Imports

At the end of the last post, we looked at how we can explicitly manage our imports and exports using a combination of text-based labels and type declarations.  In addition, we began to look at the ImportMany() attribute for importing more than one value in our extensible application.  Along with the ImportMany(), we looked at looping through the simple example to display the property of each imported type.  This approach isn't bad if the number of imported types are small; however, looping really wouldn't work well if your application loaded a very large amount of applications.  In a way, it's a great problem to have if your application has a large community based plug-in repository (i.e. Wordpress or Firefox).  There may come a time when we may need to find a specific plug-in without looping through everything.  In order to determine this, there's a couple different ways to handling this.  In this post, we're going to explore a non-MEF way of handling it using LINQ.  In a future post, we'll look at how we can expand upon this using some of the constructs that MEF provides.

Giving Our Messages a New Property

One of the nice thing about using ImportMany(), is that it tells MEF to add the various parts into a collection of type IEnumerable.  What's great about that is that any collection that is derived from IEnumerable is query-able using LINQ.  Because of this, we can use LINQ to select individual or subsets of imported parts.

In this example, we need to modify our IMessage interface to supply it a Name property.  We'll use this property as a label of our decorated part class and then query against it.  Because we're updating the definition of IMessage, we also need to implement the Name property in our SimpleMessage and SecondMessage classes.  We'll set the new properties of our classes to "Simple" and "Second" respectively as well.  Below is the code for SecondMessage at this point for illustration.

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample3
   4:  {
   5:      [Export(typeof(IMessage))]
   6:      public class SecondMessage : IMessage
   7:      {
   8:          public string MyMessage
   9:          {
  10:              get { return "Hello, From a Second Class"; }
  11:          }
  12:   
  13:          public string Name
  14:          {
  15:              get { return "Second"; }
  16:          }
  17:      }
  18:  }

LINQ to ImportMany

Now that we have a property that can be easily identified, let's update our Program class to just output SimpleMessage.MyMessage instead of both.  To do this using LINQ we first need to add the System.Linq namespace.  Next next add a Where() clause to our IEnumerable<IMessage> collection to query against the IMessage.Name property.  Finally, let's output the appropriate message.  Below is what our Program class looks like after all of these changes:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel.Composition;
   4:  using System.ComponentModel.Composition.Hosting;
   5:  using System.Linq;
   6:  using System.Reflection;
   7:   
   8:  namespace MEFExample3
   9:  {
  10:      public class Program
  11:      {
  12:          [ImportMany(typeof(IMessage))]
  13:          IEnumerable<IMessage> Messages { get; set; }
  14:   
  15:          static void Main(string[] args)
  16:          {
  17:              Program p = new Program();
  18:              p.Run();
  19:          }
  20:   
  21:          void Run()
  22:          {
  23:              Compose();
  24:   
  25:              IMessage message = (Messages.Where(m => m.Name == "Simple")).FirstOrDefault();
  26:              Console.WriteLine(message.MyMessage);
  27:              Console.ReadKey();
  28:          }
  29:   
  30:          private void Compose()
  31:          {
  32:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  33:              var container = new CompositionContainer(catalog);
  34:              container.ComposeParts(this);
  35:          }
  36:      }
  37:  }

In this post, we took our collection of imported types and filtered them using LINQ.  MEF provides additional ways to manage this using declarative Metadata attributes which we'll explore in a future post; however, for now, this method should provide a solution during this learning experience.  In the next post, we'll look at expanding our horizons by breakout our imported types into a separate assembly and using different types of part catalogs to achieve such.

Resources


kick it on DotNetKicks.comShout it

Friday, November 13, 2009

A Deeper Look at MEF's Imports and Exports

In the last article, I provided a very brief introduction to MEF and showed a very simple console application.  In this section, we'll be looking at the issues associated with that sample and diving into the various aspects of declaring your Imports and Exports to overcome those issues.  The code and samples in this post will still be within a single assembly.  Because of this, I'll may use the word Dependencies and Parts interchangeably.

The Issues with the Last Example's Simplicity

At the end of the last post, we looked at a simple console application that used MEF to wire our dependencies within the same assembly together.  Below is the code for our Program.cs and SimpleMessage.cs classes again.

Program.cs

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample2
   7:  {
   8:      class Program
   9:      {
  10:          [Import()]
  11:          string Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

SimpleMessage.cs

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample2
   4:  {
   5:      class SimpleMessage        
   6:      {
   7:          [Export()]
   8:          string MyMessage
   9:          {
  10:              get { return "Hello, Extensible World"; }
  11:          }
  12:      }
  13:  }

Now, what happens when we change our SimpleMessage class to include a new string property, we'll call it NewMessage, that's also decorated with the [Exprot()] attribute and run the application again?

   1:  [Export()]
   2:  string NewMessage
   3:  {
   4:      get { return "This is another Message."; }
   5:  }

Example2-ChangeRejectedException

Doh! Runtime Error of Type ChangeRejectedException. At this point MEF doesn't know how to wire up our dependencies properly so we'll need to help it out.  First, let's look at what the purpose of Imports and Exports are and how we can use them better.

Defining the Extensibility Contract Using Text Descriptions.

When MEF is composing the various parts of our application together, it attempts to match the members we declare as Exports to matching Imports.  In our initial example, there was only a single Export and Import that were of a matching type (string) and the mapping was easy.  Once we added the second property of the same type, MEF didn't know what to do and attempted to apply both string Exports to our only string Import.  What if we only wanted the SimpleMessage.MyMessage property to be mapped to Program.Message property?  In order to to this, MEF provides options for the Import and Export attributes that allow us to declare a specific label and/or type that can be used in the mapping process.

In order to use a label to declare the mapping, all we would have to do is change the Program.Message  and SimpleMessage.MyMessage declarations to the following:

   1:  public class Program
   2:  {
   3:      [Import("ExampleMessage")]
   4:      string Message { get; set; }
   5:   
   6:      ...
   7:  }
 
   1:  public class SimpleMessage        
   2:  {
   3:      [Export("ExampleMessage")]
   4:      public string MyMessage
   5:      {
   6:          get { return "Hello, Extensible World"; }
   7:      }
   8:   
   9:      ...
  10:  }

As you can see, we provided a simple text description/label to the Import and Export attributes that allow us better control of the mapping.  By making just this update, we can now compile and run the code successfully.

Defining the Extensibility Contract Using Types

For simple cases like this, just passing a text description or label is more than enough to handle the mappings.  But I also said that we could use Types in addition (or in place of) the descriptions to handle the mappings.  In the original example from the last post, we inferred this aspect since the properties were the same type (both were string); however, we can modify our code so that Program.Message took an object instead of just a string.

To implement this change, let's make some changes to our application.  First, let's define a new Interface called IMessage that defines the property MyMessage and have our SimpleMessage class implement it.  Next, we need to make some changes to our Export() declaration.  Since we are now passing types we will want to move the Export() decoration to be class level instead of on the SimpleMessage.MyMessage property and also explicitly declare the Export to be of our IMessage type as shown below.

   1:  [Export(typeof(IMessage))]
   2:  public class SimpleMessage : IMessage      
   3:  {
   4:      public string MyMessage
   5:      {
   6:          get { return "Hello, Extensible World"; }
   7:      }
   8:   
   9:      ...
  10:  }

Lastly, we need to update the code in our Program class by changing three things.  We need to change the Message property to be of type IMessage instead of string.  We should also change the Import() decoration on our property to explicitly expect the IMessage type. And finally, we need to change our output to Message.MyMessage due to the type change.  The updated Program.cs code is shown below.

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample2
   7:  {
   8:      public class Program
   9:      {
  10:          [Import(typeof(IMessage))]
  11:          IMessage Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message.MyMessage);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

Now when we run the application, the mappings are still correct and we now have a type specific mapping based on an interface.  In addition to explicitly declaring the type of the mapping, we can also add a label to removing any additional ambiguity if we have multiple classes that implement our IMessage interface but only want to import a specific one.  Though, what if we DID want to import more than one instance of classes that implement our IMessage interface?  Thankfully, MEF has a way for that as well.

Adding a Second Message with ImportMany()

If you can remember the beginning of this specific post, we took our SimpleMessage class and added a second string property which caused our mappings to break since MEF didn't know which string property to map to our then, Program.Message string property. With this situation we addressed it through the use of explicitly declaring the mapping through labels and type abstractions; however, there is another way.  Building on the updates from the last section, what if we were to create a new class that implements our IMessage interface and decorates itself with the Export() attribute?  Let's add a new class to our project called SecondMessage.cs and implement that scenario.  Below is the SecondMessage.cs code:

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample2
   4:  {
   5:      [Export(typeof(IMessage))]
   6:      public class SecondMessage : IMessage
   7:      {
   8:          public string MyMessage
   9:          {
  10:              get { return "Hello, From a Second Class"; }
  11:          }
  12:      }
  13:  }

When we attempt to run the application, we get the same ChangeRejectedExcemption that we did when we had 2 string exports before.  Instead of doing all of the explicit stuff we did previously, let's change our expectations of the number of objects we're importing into our Program.Message property.  MEF addresses this issue by providing an ImportMany() attribute. ImportMany() allows MEF to map many different objects that conform to the contract (label and/or type) to a single property, where as Import() is only a singular mapping.  Since we are now working with multiple instances of IMessage though, we need to update our property to be a collection, as well as update our output to loop through the results.  After applying these updates, Program.cs should resemble the below code.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel.Composition;
   4:  using System.ComponentModel.Composition.Hosting;
   5:  using System.Reflection;
   6:   
   7:  namespace MEFExample2
   8:  {
   9:      public class Program
  10:      {
  11:          [ImportMany(typeof(IMessage))]
  12:          IEnumerable<IMessage> Messages { get; set; }
  13:   
  14:          static void Main(string[] args)
  15:          {
  16:              Program p = new Program();
  17:              p.Run();
  18:          }
  19:   
  20:          void Run()
  21:          {
  22:              Compose();
  23:   
  24:              foreach(IMessage message in Messages)
  25:              {
  26:                  Console.WriteLine(message.MyMessage);
  27:              }
  28:   
  29:              Console.ReadKey();
  30:          }
  31:   
  32:          private void Compose()
  33:          {
  34:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  35:              var container = new CompositionContainer(catalog);
  36:              container.ComposeParts(this);
  37:          }
  38:      }
  39:  }

Running our application after these latest updates, we see that we get both messages as we expected.  In the next post, we'll take a quick look at how we can manage this need for looping by using LINQ; however, for now,we can see how to we're able to better manage our mappings using Imports and Exports of types and/or labels as well as working with multiple imports.

Resources


kick it on DotNetKicks.comShout it

Thursday, November 12, 2009

Working with the Managed Extensibility Framework (TOC)

This post is simply a table of contents for posts that I'm creating to help others learn about the Managed Extensibility Framework (MEF).  As new posts get published, I'll be updating the links to this page.  In addition, as I work more with MEF, I'll be adding more entries to this series to hopefully cover a wide range of scenarios while using such.

  1. An Introduction to MEF
  2. A Deeper Look at MEF's Imports and Exports
  3. LINQing to MEF Imports
  4. Playing Nice with Other Assemblies using MEF Catalogs
  5. Looking Around at Circular References in MEF
  6. Managing Composition Through Lazy Loading Parts
  7. Using MEF and Custom Configuration Sections
  8. A Configurable Type Catalog for MEF
  9. Making Part Declarations Easier with InheritedExports
  10. Hiding Parts From InheritedExport
  11. Using MEF with Signed Part Assemblies

An Introduction to MEF

Have you ever attempted to write an extensible application?  You know the kind. The applications where your boss wants to be able to add stuff to it without rewriting the entire application and with minimum costs.  Or the type of application you want to release out to the community and provide a way for them to add their own customizations to it.  We have all seen these types of applications; however, if you have ever attempted to write such, it is usually a pain to developer the core application or a pain to develop the extensions or plug-ins.  Thankfully the Managed Extensibility Framework (MEF) is available to those of us that have extensibility needs inside of the application.

Origins and Model

MEF was developed from an initiative within Microsoft in order to simply the creation of building extensible applications.  Developed by Glenn Block and others, the team developed a framework that handled the discovery and composition of the plug-ins/parts to make application extensibility easy to pickup and utilize.  In MEF, a model was developed where decorated parts, containing the extensions of the application, are discovered through catalogs and then composed within a composition container.  What is nice about this model is that it allows for composition at many levels so parts or extensions can include the ability to be extended in addition to extending an application itself (i.e. plug-ins for plug-ins).

How Does MEF Differ From IoC Containers?

During an interview on Hanselminutes episode 148 (Jan 28th, 2009), Scott Hanselman asks Glenn Block how MEF differs from IoC containers.  Glenn provided a very clear (to me) definition of the difference by saying...

You use MEF to manage a set of unknown things. You use IoC containers to manage a set of known things.

Looking at the quote, Glenn makes a good point in that when developers use an IoC container, they typically know of the various types and dependencies they are wiring up through an IoC container.  Sometimes this is configuration based to address differences between environments or just dependencies inside of the code in general. However, when you look at building an application that will allow 3rd party extensions, there's no way of knowing what will be added on.  Now MEF can act like an IoC container but to truly think of it in only that light really places mental limitations on what it can accomplish.

Writing the Hello World

When I started learning MEF, changes had been done since a number of the examples available online were created.  Since we're just getting familiar with MEF in this post, below is a very simple example where MEF is used similarly to an IoC container within a console application.  We'll take this example and greatly expand on it in the next couple of posts; however, for now, I want to just demonstrate the absolute basics to MEF. Before we dive into the code, we need to download the MEF assembly so that we can reference it in our application.

To get the necessary components for integrating MEF into our application, we need to head out to the MEF Project out at Codeplex and click on the Downloads section.  In this series, we'll be focused on MEF Preview (Beta 2) which is compatible with .Net v3.5. In the Downloads section, there should be a link for MEF_Beta_2.zip.  Download and unzip this file.  In the bin directory, you'll want to copy the System.ComponentModel.Composition.dll file.  This is the assembly used to harness the power of MEF.

Now that we have the assembly downloaded, we can create a new console application and reference it. In this demonstration, our simple console application will just output a message.  Very simple, very impractical really but we'll add more practicality over the next posts.  Our console application will need 2 classes; Program.cs and SimpleMessage.cs (shown below)

Program.cs

   1:  using System;
   2:  using System.ComponentModel.Composition;
   3:  using System.ComponentModel.Composition.Hosting;
   4:  using System.Reflection;
   5:   
   6:  namespace MEFExample1
   7:  {
   8:      class Program
   9:      {
  10:          [Import()]
  11:          string Message { get; set; }
  12:   
  13:          static void Main(string[] args)
  14:          {
  15:              Program p = new Program();
  16:              p.Run();
  17:          }
  18:   
  19:          void Run()
  20:          {
  21:              Compose();
  22:              Console.WriteLine(Message);
  23:              Console.ReadKey();
  24:          }
  25:   
  26:          private void Compose()
  27:          {
  28:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  29:              var container = new CompositionContainer(catalog);
  30:              container.ComposeParts(this);
  31:          }
  32:      }
  33:  }

SimpleMessage.cs

   1:  using System.ComponentModel.Composition;
   2:   
   3:  namespace MEFExample1
   4:  {
   5:      class SimpleMessage        
   6:      {
   7:          [Export()]
   8:          string MyMessage
   9:          {
  10:              get { return "Hello, Extensible World"; }
  11:          }
  12:      }
  13:  }
There's 3 things here we need to look at.  The Program class contains a string property called Message which is decorated with the [Import()] attribute.  This attribute tells MEF that it is an entry point for extensibility.  The 2nd thing to take note of is that our SimpleMessage class contains a string property called MyMessage and returns the message we want to output to the console window.  This property is decorated with the [Export()] attribute which informs MEF that it can be mapped to an [Import()] member of another type.  Lastly, there are the following 3 lines in our Program class's Compose() method...
   1:  var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
   2:  var container = new CompositionContainer(catalog);
   3:  container.ComposeParts(this);

These 3 lines are used by MEF to discover what parts are available in the current assembly to be imported and compose the parts into the appropriate instance that is extensible (in this case our instance of the Program class).  When we run the project, we see that our message is displayed in the console window without manually mapping SimpleMessage.MyMessage to Program.Message.


This is just a very quick and simple taste of what MEF can do.  In the following posts, we'll dive deeper into declaring Imports and Exports to ensure there not any conflicts during the mapping process as well as demonstrate some options we have on looking for parts outside of our current assembly by using different catalogs.  Until then, please feel free to check out the source code and links located at the bottom of this article for more information on MEF.

Other Resources


kick it on DotNetKicks.comShout it

Tuesday, November 10, 2009

Iowa Code Camp: Session Overview

The Iowa Code Camp was held on  November 7th, 2009 in Des Moines, IA.  With a capacity crowd and a lot of great sessions, it ended up being an awesome time with a lot of great presentations and conversations.  Like conference of this type, you never have time to hit all of the sessions you may want to; however, the ones I was able to attend were still awesome.  Below is an overview on each one.

Getting Started With Behavior Driven Development by Lee Brandt

In his presentation, Lee provided a good introduction to the concepts of BDD.  The presentation focused on the origin of BDD, where it fits, and how it's an evolution of TDD from the beginning which helped to truly set the stage.  For those that have done TDD for a bit, it provided a great introduction into bridging the gap between the business case and the code by using tests as a spec.  Through this and Lee's stressing of an Ubiquitous Language as described in various DDD circles, he showed how BDD can be used in order to provide a technique that helps to show the client what the application will do once done as well as a pseudo-burndown chart of what hasn't been finished yet.  I'm definitely looking forward to exploring BDD again in the near future.

Twitter: @LeeBrandt
Blog: http://www.geekswithblogs.net/leesblog/Default.aspx 

Going From 0 to 100 Dollars an Hour with .Net you Didn't Know by Mitchel Sellers

This session was a good session; however, it wasn't as advanced as I was hoping for.  The abstract of the session focused around using advanced features of .net in order to make you more productive; however, I was hoping for some additional tidbits beyond that of the abstract.  The primary items focused on this presentation were new tips and tricks introduced by .Net 3.5 such as Lambdas, Self Containing Properties, and LINQ. All of these items I already knew and have used them in the past which is why I was hoping for a few tidbits beyond such. That being said though it WAS a good session with a lot of good code samples to convey each concept and technology.  I still learned at least one new thing and was reminded about a few other things as well. While it didn't meet my (probably unrealistic) hopes, I cannot deny that Mitchel's presentation definitely educated a number of people who were also in his session that was overfilled.

Twitter: @MitchelSellers
Blog: http://www.MitchelSellers.com 

Open Spaces

I've been to a few open spaces discussion and have came to the conclusion that some will be good, some will be bad, and others will be between or outside of those labels.  The open spaces session at the Iowa Code Camp was an in between session.  The size of the group was smaller and comprised of a diverse set of primary skills which isn't always a bad thing though the topics in discussion didn't flow like I have experienced in other places.  We had a good conversation about how to get the information to the people that don't come to conferences or how to encourage them to come.  We also talked a little bit about MEF, coding war stories, and some of the side effects of completely rewriting/redesigning an externally facing website.  Lastly we talked a little bit about Kanban vs Scrum and the paradox of software estimation.  All in all there was some good things that came up during the conversation; however, part of me was hoping that more people would have been involved in the discussion and the topics would have been more discussion/problem solving based to an extent.

Intro to ASP.Net MVC by Chris Sutton

I've dabbled in ASP.Net MVC and have wanted to learn more about it; however, finding making the time for such is not always easy.  Everything that I've learned about such has either been about the MVC pattern itself, or about other frameworks in general like Rails or Django.  With only a few MVC Videos watched and about 3hrs worth of coding so far, I decided checking out another intro session wouldn't be a bad idea for me.  Chris Sutton did a great job with the presentation.  He explained the MVC pattern very well as well as describing how the ASP.Net MVC framework relates to it and ASP.Net in general.  He showed a couple of the typical demos for this level of session and afterwards answered all of the questions I had about the next step.  All in all it was a very good session and can't wait until I can make time for using such.

Twitter: @ChrisSutton
Blog: http://subjunctive.wordpress.com 

Silverlight for WPF Developers by Kirstin Juhl

In my opinion, none of the last block of sessions really looked appealing to me.  It wasn't the fact that I didn't think any were going to be good, it was just that I wasn't interested in the topics at hand.  I ultimately decided to check out Kirstin's presentation on what WPF Developers would need to know to transition into the Silverlight space.  While I have only dabbled in WPF a little bit, I knew a number of differences and knew the power of XAML was greater in WPF than Silverlight.  The decision to go here was my current adventures in Silverlight and see what I may be able to learn.  All in all, the session was pretty good for the purpose Kirstin was targeting.  She did a good job at explaining the differences as well as provide information on how to share components between Silverlight and WPF applications (something I knew was possible but hadn't seen an example of up to this point).  Good presentation overall.

Twitter: @KirstinJ
Blog: http://www.geekswithblogs.net/Kirstinj/Default.aspx 

Overall:

Overall, I had a great time at the Iowa Code Camp.  For being a free conference, the presentations, facilities, and of course the prizes were all top notch.  It was a great conference with some amazingly talented speakers and attendees.  All in all I can't wait to head to the next one in the April/May/June timeframe.  Hopefully some of the presentations I'm working on will be ready by then since I'd love to present one.

Friday, November 6, 2009

Reviewing This Year's Goals (2009)

Back in January, I created this post focusing around what I was hoping to accomplish this year.  I was going through my old posts and stumbled across it.  I figured it would be a good time to look over them once again to gauge my progress along with what else I may have done so far this year.

 

Learn F#:

While I do not claim to be an authority of F# by any means, I do feel comfortable in saying that I learned the bulk of the language and be able to determine where it makes sense to use it.  If time allows, I can see myself using it more and more; however, for right now, I've definitely learned a lot from such and can focus on learning other things.

 

Learn DDD:

This one I am really only about 1/2 done with.  While I have went through the information and can understand the concepts involved, I haven't had a good way of applying such yet.  There's existing applications that could benefit from the practices of DDD; but I haven't pushed myself into applying such on a new project yet.

 

Learn Silverlight 2:

I got sidetracked and ended up procrastinated on this one.  While I wanted to learn SL2, I still was a bit apathetic towards it since SL1 wasn't very impressive to me.  Thankfully, I've seen a lot of what Silverlight 3 can do and am going all out on learning more about it.  Except some posts on Silverlight 3 soon.

 

Other Things:

So what else have I been up to so far this year?  Looking back I have worked on some open source projects (namely my SchemaSpy Task for NAnt and contributing to .Net Migrations over on codeplex).  I've also focused a lot of time on keeping up to date on .Net 3.5 and other technologies that I wasn't able to fully take advantage of at a previous employer.  Lastly, I've really been focusing on TDD and just writing better code in general.  There's always room for improvements but being able to learn from what's being talked about over the past year is what's important.

 

Things on the Horizon...

Learning MEF:

The Microsoft Extensibility Framework (MEF) provides some great opportunities to make very extensible applications.  With a need to make a project extensible, I'm definitely going to be focusing on understanding MEF more.

 

Learning Silverlight 3:

I'm already in the process of working in Silverlight 3 but I have only started to write applications with such.  Just like a person who has finished their first true ASP.Net application, there's always room for improvements and things that one can learn to make things better.  I'm at that stage where there's a lot more I can learn about and I'm all for it since Silverlight 3 is awesome.

 

More SchemaSpy:

My SchemaSpy post earlier this year is one of my highest trafficked posts as well as one that I refer back to all of the time.  I'm planning on answering a few outstanding questions associated with that post and also see what else I can do with the tool to make things easier for everyone.

 

<Unknown> Things:

I always leave myself open to the unknown and unforeseen opportunities.  While November and December are usually swamped for me, I never know when inspiration will hit me and I learn something new.

Friday, October 30, 2009

Reviewing UppercuT - A Build Framework Based On NAnt

Earlier this week I went to the Kansas City .Net User Group meeting where the topic of discussion was UppercuT, a build management framework created by Rob Reynolds. The discussion was pretty good and Rob did a good job at showing a number of demonstrations on how to use the various aspects of UppercuT. All in all, I feel like the presentation got the point across as to the typical why/when/how/etc. questions.


What Is UppercuT?


UppercuT is a build management framework based on NAnt. It was created in order to establish a consistent way to build .Net applications with a minimum amount of configuration while providing areas for extensibility. In addition to just compiling, UppercuT provides a number of options to manage application versioning, automated testing, and code packaging. While it can be extended to include such steps through NAnt, UppercuT doesn't deploy code...it only stages it since every company/project's deployment strategies may be different. One nice thing that UppercuT does do in terms of deployments though is provide you instructions on how to wire it up to CruiseControl.net.


When Should UppercuT Be Used?


UppercuT provides a way for people who have not started to take advantage of automated builds to do so quickly. Because of this, it's best suited for projects that don't have automated build systems integrated into them yet. With some configuration changes, it is possible to integrate with your current scripts; however, changes would need to be made on both side to the point where it would honestly be easier to convert your current scripts to custom steps for UppercuT to take advantage on. If you currently use some build framework like MSBuild or NAnt, I would probably recommend at least checking out UppercuT to see if it's a good fit; however, if you or your company already have some system that works for you in place, it may be better to just keep with what you have.


Where Can I Download and Learn More?


You can find more information on Uppercut by going to it's project website at http://ProjectUppercuT.org. In addition, you can check out Rob's blog over at http://ferventcoder.com/ as well as on Twitter by following @ferventcoder and @ProjectUppercuT.


kick it on DotNetKicks.comShout it