EDAMLibrary : Evernote Library for C#

I recently pushed a library onto bitbucket.  It’s used for integrating with the popular note-taking, cloud-syncing, capture application Evernote.  I started using Evernote in February of this year and I’m addicted to it now.  I scan and tag tons of information and have it easily available at all times.  My data is sync’d to the cloud and accessible via a Windows client, the web and various mobile platforms (Blackberry, iPhone, Android).

While Evernote provides an API for accessing the data, it has a few organization issues that need to be overcome before you can use it.  To make it easier for those just wanting to play around with Evernote, I combined everything provided by Evernote into a single library.

And remember, if you want to develop something that integrates with Evernote, you’ll have to request an API key.  It’s a pretty simple process that just takes a few minutes.

Technorati Tags: ,,,
Posted by PSteele | 1 comment(s)
Filed under: ,

Rhino.Mocks, Lambdas and Expectations

An interesting post on the Rhino.Mocks users list that I thought I’d share.

Background

Let’s start with a simple interface for an item:

public interface IItem
{
    void DoFoo();
    void DoBar();
}

Now let’s say we have a custom collection of these IItem objects.  In this collection, we have a “Process” method and we’d like that process method to determine which method to call on each IItem – either DoFoo() or DoBar().  We’ll accomplish this with an Action<IItem> delegate:

public interface IItemCollection
{
    void Add(IItem item);
    void Remove(IItem item);
    void Process(Action<IItem> action);
}

Now we have a service that works with that collection:

public class SomeService
{
    private IItemCollection items;
 
    public SomeService(IItemCollection items)
    {
        this.items = items;
    }
 
    public void Foo()
    {
        items.Process(i => i.DoFoo());
    }
 
    public void Bar()
    {
        items.Process(i => i.DoBar());
    }
}

So now, we want to write a unit test for SomeService to make sure that the proper method (DoFoo/DoBar) is called depending on which service method we call (Foo/Bar).

Unit Test

[TestMethod]
public void TestMethod1()
{
    // arrange
    var items = MockRepository.GenerateMock<IItemCollection>();
    var service = new SomeService(items);
 
    // act
    service.Foo();
 
    // assert
    items.AssertWasCalled(c => c.Process(i => i.DoFoo()));
}

This all seems pretty simple (it is – it’s just a sample).  But if you run the test, it fails.  Why?

Explanation

The answer lies in some of the plumbing that lambdas do for us.  Remember that lambdas are just shortcuts for anonymous delegates.  And anonymous delegates are shortcuts for writing a totally separate method.  If we “reverse engineer” how this code looks to the compiler, we’ll see something like this for SomeService.Foo():

public void Foo()
{
    items.Process(OnAction);
}
 
private void OnAction(IItem i)
{
    i.DoFoo();
}

See how the actual call being made is to a private method inside the SomeService class.  If we look at our unit test (which also uses a lambda as part of the expectation), we’ll see something similar:

[TestMethod]
public void TestMethod1()
{
    ...
 
    // assert
    items.AssertWasCalled(c => c.Process(OnAction));
}
 
private void OnAction(IItem i)
{
    i.DoFoo();
}

Again, another private method inside the unit test assembly.  So we’ve told Rhino.Mocks to make an assertion that a call was made to IItemCollection.Process and a delegate to the private OnAction within the test class was called.  In reality, the delegate passed to IItemCollection.Process was to the private method within the SomeService class.  Therefore, Rhino.Mocks reports a failure.

It’s important to understand how lamdas and anonymous methods work.  They make our job as software developers a whole lot easier, but there are some things to watch out for.

Technorati Tags: ,,,
Posted by PSteele | 1 comment(s)
Filed under: , ,

Building Paths Fluently

If you ever need to “build” a path (i.e. “C:\folder1\subfolder”), you really should be using Path.Combine.  It makes sure the trailing directory separator is in between the two paths (and it puts the appropriate character in – DirectorySeparatorChar).  I wanted an easier way to build a path than having to constantly call Path.Combine so I created a handy little extension method that lets me build paths “fluently”:

public static string PathCombine(this string path1, string path2)
{
    return Path.Combine(path1, path2);
}

Now I can write code like this:

var dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
    .PathCombine("Folder1")
    .PathCombine("Folder2");

Technorati Tags: ,,
Posted by PSteele | 4 comment(s)
Filed under:

Updates to Nino’s .hgignore files for Visual Studio

As I move more of my repositories from SVN to Mercurial, I’m constantly referring to Nino’s sample .hgignore file he provided for Visual Studio developers.  I always start with his file but add a few more lines and thought I’d share them here.  Start with Nino’s .hgignore file and add the following two lines at the bottom:

TestResults\*
glob:desktop.ini

Obviously, we don’t need to version our TestResults.  And I don’t want to version the occasional desktop.ini that gets generated by XP when you tweak folder settings.

Verbosity Isn’t Always a Bad Thing

There was a message posted to the Rhino.Mocks forums yesterday about verifying a single parameter of a method that accepted 5 parameters.  The code looked like this:

 
[TestMethod]
public void ShouldCallTheAvanceServiceWithTheAValidGuid()
{
    _sut.Send(_sampleInput);
    _avanceInterface.AssertWasCalled(x => x.SendData(
        Arg<Guid>.Is.Equal(Guid.Empty),
        Arg<string>.Is.Anything,
        Arg<string>.Is.Anything,
        Arg<string>.Is.Anything,
        Arg<string>.Is.Anything));
}

Not the prettiest code, but it does work.

I was going to reply that he could use the “GetArgumentsForCallsMadeOn” method to pull out an array that would contain all of the arguments.  A quick check of “args[0]” would be all that he needed.  But then Tim Barcz replied with the following:

Just to help allay your fears a bit...this verbosity isn't always a bad thing.  When I read the code, based on the syntax you have used I know that for this particular test no parameters matter except the first...extremely useful in my opinion.

An excellent point!  We need to make sure our unit tests are as clear as our code.

Technorati Tags: ,
Posted by PSteele | 1 comment(s)
Filed under: , ,

Backing Up with FTP

I finally set aside some time to upgrade to Windows 7.  Most everyone else in the office has already upgraded.  I was holding out so I could finish up a few client projects and get the Ann Arbor GiveCamp website up and running.  Now it’s my turn!

A Clean Install

A few people told me NOT to do an upgrade install of Windows 7.  Instead, do a clean install by formatting your hard drive.  Obviously, you’ll want to make sure everything is backed up before doing this.  At home, I have a FreeNAS server that does daily backups via rsync (thanks to DeltaCopy).  However, I wasn’t quite backing up everything so I had a little extra work to do.  Actually, I found quite a bit of important stuff that wasn’t on my daily schedule.

I originally was using Windows Explorer to copy/paste directories.  However, when you’ve got a lot of copying to do, it’s not very efficient.  Small hiccups along the way usually halt the entire operation and you have to start over.  I decided I’d just use FileZilla and FTP everything over to my NAS server (since it can be an FTP server as well).  I can place a whole ton of files in a queue, control the queue processing and easily retry failed transfers.  This type of control reduced my backup time immensely.

File Transfer Mode

The one problem with using FTP to backup files is that FTP has two different transfer modes: Binary and ASCII.  When moving files between a windows and unix-based system (as I was since FreeNAS is based on FreeBSD), ASCII/text files are converted so the CR/LF from windows gets converted just to a CR in unix.  Most FTP clients (including Mozilla) have an “auto-detect” mode and pick the appropriate mode to use based on the file type.  They always transfer things like .txt and .xml files as ASCII and other files like .png, .bmp or .mp3 as binary and everything just works.

But there are exceptions!  After moving some of my files back to my Win7 machine (using FileZilla in the opposite direction), I noticed that my Mercurial repositories were showing up as having changes (I committed everything before re-paving my machine).  And one repository was reporting a corrupt index.  Ugh…  As I started poking around inside the Mercurial data storage files, I started to think that perhaps some of these were transferred as ASCII when they actually should have been binary!

Once I realized what had happened, I felt pretty stupid.  Since I was using FTP solely as a backup tool (and not really to “transfer” a file for use on the other machine), I should have forced FileZilla to use binary transfer so everything would have been an exact copy, byte for byte.  I did a quick test of a Mercurial repository and transferred it in both “auto” mode as well as “binary” mode.  Of course, binary mode went back and forth without a hitch.

Fixing My Repositories

This isn’t FileZilla’s fault.  If I figured out exactly what caused the file corruption (and in what file), I probably could have just configured FileZilla to transfer those specific file types as binary.  Luckily, the repositories that showed some corruption were small, private repositories that only I used.  And the Mercurial wiki had a page that showed me how to fix the problem.  I ended up using the “Recovery using Convert extension” option.  It fixed my repositories and I didn’t loose any changesets.  Nice!

Posted by PSteele | 1 comment(s)
Filed under: ,

Tweaking log4net Settings Programmatically

A few months ago, I had to dynamically add a log4net appender at runtime.  Now I find myself in another log4net situation.  I need to modify the configuration of my appenders at runtime.

My client requires all files generated by our applications to be saved to a specific location.  This location is determined at runtime.  Therefore, I want my FileAppenders to log their data to this specific location – but I won't know the location until runtime so I can't add it to the XML configuration file I'm using.

No problem.  Bing is my new friend and returned a couple of hits.  I made a few tweaks to their LINQ queries and created a generic extension method for ILoggerRepository (just a hunch that I might want this functionality somewhere else in the future – sorry YAGNI fans):

public static void ModifyAppenders<T>(this ILoggerRepository repository, Action<T> modify) where T:log4net.Appender.AppenderSkeleton
{
    var appenders = from appender in log4net.LogManager.GetRepository().GetAppenders()
                        where appender is T
                        select appender as T;
 
    foreach (var appender in appenders)
    {
        modify(appender);
        appender.ActivateOptions();
    }
}

Now I can easily add the proper directory prefix to all of my FileAppenders at runtime:

log4net.LogManager.GetRepository().ModifyAppenders<FileAppender>(a =>
                {
                    a.File = Path.Combine(settings.ConfigDirectory,
                                          Path.GetFileName(a.File));
                });
Thanks beefycode and Wil Peck.

Technorati Tags: ,,
Posted by PSteele | 2 comment(s)
Filed under: , ,

Ann Arbor Day of .NET 2010 Recap

Had a great time at the Ann Arbor Day of .NET on Saturday.  Lots of great speakers and topics.  And chance to meet up with friends you usually only communicate with via email/twitter.

My Presentation

I presented "Getting up to speed with C# 3.5 — Just in time for 4.0!".  There's still a lot of devs that are either stuck in .NET 2.0 or just now moving to .NET 3.5.  This presentation gave highlights of a lot of the key features of 3.5.  I had great questions from the audience.  Afterwards, I talked with a few people who are just now getting in to 3.5 and they told me they had a lot of "A HA!" moments when something I said finally clicked and made sense from a code sample they had seen on the web.  Thanks to all who attended!

A few people have asked me for the slides and demo.  The slides were nothing more than a table of contents.  90% of the presentation was spent inside Visual Studio demo'ing new techniques.  However, I have included it in the ZIP file with the sample solution.  You can download it here.

Dennis Burton on MongoDB

I caught Dennis Burton's presentation on MongoDB.  I was really interested in this one as I've missed the last few times Dennis had given it to local user groups.  It was very informative and I want to spend some time learning more about MongoDB.  I'm still an old-school relational guy, but I'm willing to investigate alternatives.

Brian Genisio on Prism

Since I'm not a Silverlight/WPF guy (yet), I wasn't sure this would interest me.  But I talked with Brian for a couple of minutes before the presentation and he convinced me to catch it.  And I'm glad he did.  Prism looks like a very nice framework for "composable UI's" in Silverlight and WPF.  I like the whole "dependency injection" feel to it.  Nice job Brian!

GiveCamp Planning

I spent some time Saturday working on things for the upcoming GiveCamp (which is why I only caught a few sessions).  Ann Arbor's Day of .NET and GiveCamp have both been held at Washtenaw Community College so I took some time (along with fellow GiveCamp planners Mike Eaton and John Hopkins) to check out the new location for Ann Arbor GiveCamp this year!

In the past, WCC has let us use the Business Education (BE) building for our GiveCamp's.  But this year, they're moving us over to the Morris Lawrence (ML) building.  Let me tell you – this is a step UP!  In the BE building, we were spread across two floors and spread out into classrooms.  Plus, our opening and closing ceremonies were held in the Liberal Arts (LA) building – a bit of a walk from the BE building.

In the ML building, we're together for the whole weekend.  We've got a large open area (which can be sectioned off if needed) for everyone to work in:

IMG00083-20100501-1031

 

Right next to that, we have a large area where we can set up tables and eat.  And it helps that we have a wonderful view while eating (yes, that's a lake out there with a fountain):

IMG00084-20100501-1037

The ML building also has showers (which we'll have access to!) and it's own auditorium for our opening and closing ceremonies.

All in all, this year's GiveCamp will be great! Stay tuned to the Ann Arbor GiveCamp website.  We'll be looking for volunteers (devs, designers, PM's, etc…) soon!

Posted by PSteele | with no comments

Putting a base in the middle

From Eric Lippert's Blog:

Here’s a crazy-seeming but honest-to-goodness real customer scenario that got reported to me recently. There are three DLLs involved, Alpha.DLL, Bravo.DLL and Charlie.DLL. The classes in each are:

public class Alpha // In Alpha.DLL
{
  public virtual void M()
  {
    Console.WriteLine("Alpha");
  }
}

public class Bravo: Alpha // In Bravo.DLL
{
}

public class Charlie : Bravo // In Charlie.DLL
{
  public override void M()
  {
    Console.WriteLine("Charlie");
    base.M();
  }
}

Perfectly sensible. You call M on an instance of Charlie and it says “Charlie / Alpha”.

Now the vendor who supplies Bravo.DLL ships a new version which has this code:

public class Bravo: Alpha
{
  public override void M()
  {
    Console.WriteLine("Bravo");
    base.M();
  }
}

The question is: what happens if you call Charlie.M without recompiling Charlie.DLL, but you are loading the new version of Bravo.DLL?

The customer was quite surprised that the output is still “Charlie / Alpha”, not “Charlie / Bravo / Alpha”.

Read the full post for a very interesting discussion of the design of C#, the CLR, method resolution and more.

Technorati Tags: ,,
Posted by PSteele | with no comments
Filed under:

Talks Submitted for Ann Arbor Day of .NET 2010

Just submitted my session abstracts for Ann Arbor's Day of .NET 2010.

 

Getting up to speed with .NET 3.5 -- Just in time for 4.0!

Yes, C# 4.0 is just around the corner.  But if you haven't had the chance to use C# 3.5 extensively, this session will start from the ground up with the new features of 3.5.  We'll assume everyone is coming from C# 2.0.  This session will show you the details of extension methods, partial methods and more.  We'll also show you how LINQ -- Language Integrated Query -- can help decrease your development time and increase your code's readability.  If time permits, we'll look at some .NET 4.0 features, but the goal is to get you up to speed on .NET 3.5.

 

Go Ahead and Mock Me!

When testing specific parts of your application, there can be a lot of external dependencies required to make your tests work.  Writing fake or mock objects that act as stand-ins for the real dependencies can waste a lot of time.  This is where mocking frameworks come in.  In this session, Patrick Steele will introduce you to Rhino Mocks, a popular mocking framework for .NET.  You'll see how a mocking framework can make writing unit tests easier and leads to less brittle unit tests.

 

Inversion of Control: Who's got control and why is it being inverted?

No doubt you've heard of "Inversion of Control".  If not, maybe you've heard the term "Dependency Injection"?  The two usually go hand-in-hand.  Inversion of Control (IoC) along with Dependency Injection (DI) helps simplify the connections and lifetime of all of the dependent objects in the software you write.  In this session, Patrick Steele will introduce you to the concepts of IoC and DI and will show you how to use a popular IoC container (Castle Windsor) to help simplify the way you build software and how your objects interact with each other.

If you're interested in speaking, hurry up and get your submissions in!  The deadline is Monday, April 5th!

Technorati Tags: ,,
More Posts Next page »