DictionaryAdapter is Love (Part 2)

Posted on Tuesday, September 07 2010 by The Admin

In our last installment, we learned the basics of how to use DictionaryAdapter to use an interface to access loosely structured data.  This time, we’re going to show a somewhat more complex scenario than simple properties.  Consider the following:

 

        static void Main(string[] args)
        {
            var dict = new Dictionary<string, object>()
                {
                    { "UserId", 1234567 },
                    { 
                        "UserName", new Dictionary<string,object>()
                        {
                            { "UserFirstName", "Tim" },
                            { "UserLastName", "Rayburn" }
                        }
                    }
                };
        }

As you can see, we’ve nested dictionaries this time, where the UserName key has a value of another dictionary, with two keys itself.  The simplest model for this is to simple add another interface, IUserName, which represents this nested data.  Here is a look at that code:

    public interface IUserData
    {
        [Key("UserId")]
        int Id { get; set; }

        [Key("UserName")]
        IUserName Name { get; set; }
    }

    public interface IUserName
    {
        [Key("UserFirstName")]
        string FirstName { get; set; }

        [Key("UserMiddleName")]
        string MiddleName { get; set; }

        [Key("UserLastName")]
        string LastName { get; set; }
    }

So lets see how DictionaryAdapter (it’s called DA by its friends, which if you’re still reading at this point you clearly are) … so lets see how DA handles this scenario.  We’d hope that something like this would work:

        static void Main(string[] args)
        {
            var dict = new Dictionary<string, object>()
                {
                    { "UserId", 1234567 },
                    { 
                        "UserName", new Dictionary<string,object>()
                        {
                            { "UserFirstName", "Tim" },
                            { "UserLastName", "Rayburn" }
                        }
                    }
                };

            var data = new DictionaryAdapterFactory().GetAdapter<IUserData>(dict);

            Console.WriteLine(data.Name.FirstName);
        }

Does it? Nope.  Why?  Let’s look at the details:

System.InvalidCastException was unhandled
  Message=Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]' to type 'Part2.IUserName'.
  Source=Part2.Part2.IUserData.DictionaryAdapter
  StackTrace:
       at Part2.UserDataDictionaryAdapter.get_Name()
       at Part2.Program.Main(String[] args) in C:\source\BlogPosts\DictionaryAdapterIsLove\Part2\Program.cs:line 32
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

I have to give credit where credit is due, this make pretty darned clear what the problem is.  Our nested dictionary is not, itself, being wrapped so when DA tries to retrieve it and cast it to IUserName it, obviously, cannot.

That’s great Tim … but how do I fix that?

Enter behaviors.  Dictionary adapter has an abstraction over anything that modifies how it does its work called Behaviors.  You can create behaviors for all sorts of things, but one of them is Property Getting.  To modify this behavior you need to do two things:

  1. Create a class which implements the IDictionaryPropertyGetter interface.
  2. Modify your request to the Factory to request your DA use that behavior.

If we take a peek at IDictionaryPropertyGetter you will see the following definition:

    public interface IDictionaryPropertyGetter : IDictionaryBehavior
    {
        object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue, PropertyDescriptor property, bool ifExists);
    }

As you can see this isn’t terribly complex.  But you’ll also notice that it implements IDictionaryBehavior, so lets take a peek at that shall we?

    public interface IDictionaryBehavior
    {
        int ExecutionOrder { get; }
    }

Again, not very complex at all.  So we need a class that will implement both of these, and which will examine the propertyDescriptor parameter to determine if the requested Type is itself an interface which is not assignable from the type of storedValue but that storedValue is assignable from IDictionary.  If those conditions are met, we can create another DictionaryAdapter to adapt to the new interface.  Here is a simple example of that class :

    public class NestedDictionaryGetterBehavior : IDictionaryPropertyGetter
    {
        public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue, PropertyDescriptor property, bool ifExists)
        {
            if (property.PropertyType.IsAssignableFrom(storedValue.GetType()))
            {
                return storedValue;
            }

            if (property.PropertyType.IsInterface && IsDictionary(storedValue.GetType()))
            {
                return dictionaryAdapter.This.Factory.GetAdapter(property.PropertyType, storedValue as IDictionary);
            }

            return storedValue;
        }

        public int ExecutionOrder
        {
            get { return 0; }
        }

        private bool IsDictionary(Type type)
        {
            return typeof(IDictionary).IsAssignableFrom(type);
        }
    }

As you can see, some code, but not lots of code.  Our example should skip the first if statement and go into the second one, returning the new DictionaryAdapter.  Now we need to do step 2, modify our original request to the Factory to add our behavior.  Here is what the code looks like once we’ve done that:

        static void Main(string[] args)
        {
            var dict = new Dictionary<string, object>()
                {
                    { "UserId", 1234567 },
                    { 
                        "UserName", new Dictionary<string,object>()
                        {
                            { "UserFirstName", "Tim" },
                            { "UserLastName", "Rayburn" }
                        }
                    }
                };

            var data = new DictionaryAdapterFactory()
                .GetAdapter(typeof(IUserData),
                dict,
                new DictionaryDescriptor().AddBehavior(new NestedDictionaryGetterBehavior())) as IUserData;

            Console.WriteLine(data.Name.FirstName);
            Console.ReadLine();
        }

Now, that gets a little tedious to do every time, and I can assure you that Craig Neuwirt hates tedious.  As such, DictionaryAdapter will look for any attributes on your interface which implement IDictionaryBehavior and add them for you automatically.  So with a very simple refactoring of our class:

    public class NestedDictionaryGetterBehavior : Attribute, IDictionaryPropertyGetter

We can then modify our interface:

    [NestedDictionaryGetterBehavior]
    public interface IUserData
    {
        [Key("UserId")]
        int Id { get; set; }

        [Key("UserName")]
        IUserName Name { get; set; }
    }

And move back to a very simple DictionaryAdapterFactory request:

            var data = new DictionaryAdapterFactory().GetAdapter<IUserData>(dict);

And I think that’s enough for this time.

DictionaryAdapter is Love (Part 1)

Posted on Friday, September 03 2010 by The Admin

Nestled deep within the Castle Project repository, there is a wonderful library maintained by Improving Enterprises’ own Craig Neuwirt which can forever change how you deal with the assortment of Key/Value pair structures in our programming life.  That library is called DictionaryAdapter, or more properly Castle.Components.DictionaryAdapter and the source can be found at : http://github.com/castleproject/Castle.Core

So how does this library work?  Let’s take a quick tour around, shall we?

So you’ve got a Dictionary…

        static void Main(string[] args)
        {
            var dict = new Dictionary<string, object>()
                {
                    { "UserId", 1234567 },
                    { "UserFirstName", "Tim" },
                    { "UserLastName", "Rayburn" }
                };
        }

We deal with dictionaries like this all the time in .NET, the easiest example of which is ASP.NET Session but many others exist.  Now lets assume that we wanted to access this information in a structured way.  That is to say, instead of writing something like:

        public static string UglyWayToGetUserFirstName(Dictionary<string, object> dict)
        {
            string userFirstName = "UserFirstName";
            if (dict.ContainsKey(userFirstName)) 
                return dict[userFirstName] as string;
            return null;
        }

I instead want to write code which access the information using a strongly typed interfaced like this:

    public interface IUserData
    {
        int UserId { get; set; }
        string UserFirstName { get; set; }
        string UserLastName { get; set; }
    }

Which would produce code like this:

        public static string CleanWayToGetUserFirstName(IUserData data)
        {
            return data.UserFirstName;
        }

How do I do that?  DictionaryAdapter to the rescue.  Add a reference to Castle.Core, and a using statement for Castle.Components.DictionaryAdapter and then the following code will work:

        static void Main(string[] args)
        {
            var dict = new Dictionary<string, object>()
                {
                    { "UserId", 1234567 },
                    { "UserFirstName", "Tim" },
                    { "UserLastName", "Rayburn" }
                };

            IUserData data = new DictionaryAdapterFactory()
               .GetAdapter<IUserData>(dict);

            Console.WriteLine(CleanWayToGetUserFirstName(data));
            Console.ReadLine();
        }

Simple, eh?  But there is much more coming.  As you can see, there is a default convention that matches the property name of our interface to the key in the dictionary.  Lets assume that you’re the type of person who believes having the word User in front of each property on the interface is a bad idea, but keeping it on the keys which lack the context of being IUserData makes sense.  No problem, enter aliasing.  Modify your interface like so:

    public interface IUserData
    {
        [Key("UserId")]
        int Id { get; set; }

        [Key("UserFirstName")]
        string FirstName { get; set; }

        [Key("UserLastName")]
        string LastName { get; set; }
    }

And now your  interface main method (no longer using our rather useless CleanWayToGetUserFirstName example above) can be refactored like so:

        static void Main(string[] args)
        {
            var dict = new Dictionary<string, object>()
                {
                    { "UserId", 1234567 },
                    { "UserFirstName", "Tim" },
                    { "UserLastName", "Rayburn" }
                };

            IUserData data = new DictionaryAdapterFactory()
                .GetAdapter<IUserData>(dict);

            Console.WriteLine(data.FirstName);
            Console.ReadLine();
        }

That’s a good introduction to the basics of DictionaryAdapter, but there is a lot more depth here that I hope to cover in future posts.

Work for the Best … Pity the Rest

Posted on Wednesday, August 25 2010 by The Admin

Do you work for a company that truly, I mean truly, values technical leadership and skills?  Do they value your abilities to communicate with non-IT staff?  Do they encourage you to get involved in the community through a bonus compensation plan that includes things as simple as attending a local user group?  No?  Then perhaps its time to Improve your outlook…

Improving Logo

Improving Enterprises, my employer since March of 2009, is just such and employer.  Improving has to be doing something right, after all we’ve just been named to the Inc. 500/5000 list, placing us at #210 in the nation, but number #10 fastest growing company in Dallas, and #18 in IT Services nationwide.  And this is our second year on that list.

inc5000_2010_logo

Now why am I telling you all of this?  Is it just to brag about how great my life at Improving is?  To rub in your face that I get to work for a company with 4 Microsoft MVPs on staff?  No, none of that…

It’s because we’re hiring … and in a big way!

How big?  We’ve got over 20 positions open at the current time.  Are we just looking for rock stars?  Not at all … we’ve got positions available at Consultant, Senior Consultant, and Principal Consultant available.  Consultants are generally people just out of school, or with a year or two of experience, and it goes up from there.

Why should you work for us?

For me, it is just this simple : I like to be challenged at work, I want to feel that my co-workers are challenging me to expand my horizons.  I’ve felt that way every day since I started at Improving.

Other perks?  How about an annual company retreat to Vegas.  A bonus plan.  And an incredible work environment.

CALL TO ACTION – It’s time to work for the best, and pity the rest … if you’re interested in working for an incredible organization like Improving, then drop me an email with your resume to Tim@TimRayburn.net and we’ll get you started along the process.

Why should I go to Dallas TechFest?

Posted on Monday, July 26 2010 by The Admin

Banner 2010

So I’m always pushing Dallas TechFest, and that I believe it is the best value day you can spend away from work, but you don’t have to listen to me…

  • “There are also some big names from other technologies at TechFest as well, such asScott Davis (Grails guru extraordinaire), Ted Neward (.NET developer and consultant), Mark Piller (Midnight Coders), and Craig Walls (SpringSource) to name but a few.  Sounds excellent, right? Well, today's your lucky day. If you haven't registered yet there's still time, and there's a big discount to boot! Register now and use the discount code coldfusion to get in for only $25. That's right, a mere $25 for all this geeky goodness.” from Matt Woodward
  • “If you are unable to attend CFUnited and you are in or are able to travel to the Dallas, TX area you should really check out Dallas TechFest.  I'll be speaking there again this year on Getting Started with Mura CMS Development.” from Steve Good
  • “This year’s schedule features well-known and local speakers from across 6 different communities including .NET, Java, PHP, Adobe, ColdFusion, Apple and IT Pro.  Registration is normally $50, but if you use the code “dotnet” you can get a $25 discount!  Make sure you sign up today as space is filling up quickly” from Chris Koenig

If you haven’t registered yet, then what are you waiting for?  Online registration is open for the another day or so, so head over to http://DallasTechFest.EventBrite.Com and use one of the discount codes above to register for only $25.  Or, register at the door, but that will cost $60.  Feel like registering ahead of time now?  I thought so.

Another Database Option - MongoDB

Posted on Saturday, June 12 2010 by The Admin

logo-mongodb It’s been far to long since I’ve talked here about what I’m working on, so it is time to correct that.  I’ve been working with a client who has some very unique business requirements, and one of them deals with a lot of flexibility of their data storage.  As such we were looking into different types of storage, because while SQL Server is in fact a wonderful product, it is not known for its flexibility of storage.

This quest led us to the door of a large number of databases in the “No SQL” arena, and eventually to MongoDB.  MongoDB is a document database, which stores what can best be described to the .NET Developer as a Dictionary<string,object>.  This structure allows for nesting of structures (where the object stored is another Dictionary) and is a very clever structure if you ask me.  But, document databases do not work like relational databases.  There are several important things you need to realize:

  1. Documents databases do not generally support the concept of JOINS.  If you retrieve data, and it refers to other data, then you need to make another call to the database to retrieve that data.
    • This leads to the core concept of preferring to embed (in the dictionary) data rather than refer to data.
  2. Document databases do not generally support a defined structure, they do not have tables but rather “collections” which have no definition in the database.  It is perfectly valid for one entry in a collection to have a key “dateOfAccount” which is a string type, and another with that same key as a date.
  3. Document databases do not include a validation structure, any validation of the data (including structural data as noted above) must be enforced by your application.

In the world of .NET there are several drivers, but the one my team, David O’Hara and Craig Neuwirt and I, decided on was MongoDB-CSharp.  They have just released version 0.9 beta 1, which moves the driver a lot closer to a familiarity level for most .NET developers.  Now we had to address on our project all of the above problems, and key to us doing so has been a component called DictionaryAdapater from the Castle Project.  But that is a topic for another blog post.

iPad becomes toughPad

Posted on Monday, June 07 2010 by The Admin

So on Thursday afternoon, I picked up a beautiful new iPad 16gb WiFi.  As an avid iPhone user, I find the device to be everything I expected, and used it all day Friday happily.

On Saturday night, technically Sunday morning, I was leaving the home of my brother after a night of playing poker, and drove out of his driveway with the iPad on the roof of my Suburban.  My drive was 5 minutes of city streets, and somewhere along the way, on a road I was going about 30 miles per hour on, my iPad took the plunge.  Now, of course, I didn’t notice this at the time.  So it fell into the roadway and I drove on.  When I finally realized it was missing when I got home, I called my brother who went out from his place, we met in the middle and he found it in the road for me.  The iPad had been in a black Belkin neoprene case I had purchased for my Kindle DX while I waited for Amazon to deliver my Speck CandyShell case, and the zipper was now ruined, so my brother left the tearing open of the case to me.  What did I find inside, after a 5 foot fall going 30 mph and then (as I would soon discover) having been run over by another car?  Here are the photos…

IMG_0200 IMG_0206

IMG_0208[1]

IMG_0201 IMG_0202

 IMG_0205 IMG_0204

As you can see, clearly the device was run over, likely while laying glass-down in the case on the road, by a vehicle.  The device though continues to work PERFECTLY.  The screen has two areas showing some extra brightness where I suspect it is being pressed on from the rear, but despite this incredible event that I would have expected most devices to have been destroyed by, the iPad came through a little worse for wear but otherwise unscathed.  The sides of the aluminum case are puckering away from the screen slightly, and the corners are roughed up a bit, but overall it came through amazingly well.

Thank you Apple for a quality product, and saving me from being killed by my wife when she heard about this event.

Dallas TechFest 2010 Registration Is Open

Posted on Tuesday, May 25 2010 by The Admin

Large Logo 2010

I’m thrilled to announce that registration is open for Dallas TechFest 2010 at http://dallastechfest.eventbrite.com

Who is speaking you ask?  Well our incredible team of web volunteers are hard at work on a refresh of our website, but in the meantime, here are some names and topics from the .NET Track:

  • ASP.NET MVC 2 and Azure Table Storage - Chander Dhall
  • Particle Physics Engine in Silverlight and ASP-mvc?! - Amir Rajan
  • The Rich Standard: Getting Familiar with HTML 5 - Todd Anglin
  • Hard Lessons Learned From Being Stupid About TDD - Matt Hinze
  • Intro To Generics 0 to 60 - Devlin Liles
  • M-V-V-M in Silverlight 4 - Caleb Jenkins
  • Unit Testing SharePoint using TypeMock - Kyle Kelin
  • 10 Practices every developer should start right now - Caleb Jenkins
  • Monotouch for the iPhone - Casey Watson
  • Dropping ACID: Building Scalable Systems That Work - Chris Patterson

 

Silverlight, SharePoint, iPhone, HTML5, as you can see we’ve got a packed schedule of .NET goodness … and that’s not to mention the Flex, ColdFusion, PHP, and Java tracks!

Why go to the MVP Summit?

Posted on Saturday, February 20 2010 by The Admin

NDA Reminder Every year Microsoft hosts an event they refer to as the MVP Global Summit in the Seattle area.  This event is invitation only event where those who have been recognized as Microsoft MVPs get to meet with their product groups, discuss strategy, impart real-world scenarios, and learn what is coming down the pipe.  The event is simply wonderful, where else can you get a chance to interact with the people directly responsible for parts of the Microsoft eco-system you care about most deeply.  Of course, such openness does not come without restriction.  The MVPs are all under a Non-Disclosure Agreement (NDA) which means that for 90%+ of what we are told, we cannot discuss it with other people.

You can’t discuss it?  Why go then?!

A fair question, with at least four answers. So let’s go through them.

First – I can’t discuss things, but I still know them.

When thinking about the trip to the Summit you must remember that you’re learning things far before the public will, but that does not mean that the public will never learn these things.  Much of what is discussed will eventually become public information, and once it is those who have been to the Summit will have had the most time to internalize and strategize on the information, often meaning they will be able to act on that information more quickly.  Also just because I can’t share my knowledge does not mean I can’t share my judgment.  I can use the information I have received to inform the choices I make for my own personal work and what I do for my clients.

Second – Meet the Team

Every Summit is a chance to meet new people within Microsoft who are working on your area of expertise and interest, to put a face with a name, and to collect business cards or email aliases.  This can be wonderful later on if you want to provide feedback or ask a short question during the 99% of the year that isn’t the MVP Summit.

Third – Bond with your Local MVPs

When you travel to the MVP Summit you get a chance to spend time strengthening your relationships with the MVPs in your area.  Your local MVPs are the backbone of your community, and getting to know them better will help you help your community better.  You’ve got time during the Summit to discuss plans for future events, eat, drink and be merry.

Fourth – Meet MVPs from around the world…

This may seem like a repeat of the entry above, but meeting MVPs from outside your local area has a different purpose.  Your making connections that open up an exchange of ideas.  You’re putting names with faces from Twitter, Facebook, StackOverflow and other sites.  You never know when a passing conversation about your interest with some technology might not result in you being able to help a company half way around the world make a wiser technical decision.  Absolutely key.  Again, eat, drink and be merry.

Conclusion

Rather obviously a lot of what the MVP Summit is about is networking, but you’re and MVP right?  You network, help people, organize meetings, answer questions, in general you are a community leader, and influencer.  And so are ALL of those other MVPs.  Even if every MVP touched merely as many people as a small user group, say 50/month people, then the 1400 MVPs who just left the Summit in 2010 represent 840,000 developer touches.  And those numbers are low.  From blog posts, to conferences, and more an MVP has huge reach … which is why we were invited to begin with.

Thank you to Microsoft, the Product Groups, the Developer Evangelists, and the incredible MVP Leads for making this Summit a smashing success!

Dallas TechFest 2010 – Call For Speakers

Posted on Wednesday, February 17 2010 by The Admin

Dallas TechFest 2010

I’m thrilled to announce that Dallas TechFest 2010 has set a date of July 30th, 2010 and is currently engaged in a Call For Speakers looking for those in all sorts of technology areas who wish to speak.  If you’ve got expertise in .NET, Java, Ruby, PHP, ColdFusion, Python, Flex or anything else then send in an abstract and see if you can secure a speaking slot at Dallas TechFest 2010.

Sometime in March we will be opening registration, but in the meantime mark the date on your calendar, and get ready for our registration drive.  Like in previous years, if you recommend people to register you will be entered to win a great prize.  What prize? Hmmm….  Well it’s got a touch screen, a 3G modem, and a huge app store.

Gravatars in ASP.NET MVC using HtmlHelper

Posted on Wednesday, December 23 2009 by Tim

I’m working on a side-project right now that is using Gravatars and found the wonderful article by Ryan Lanciaux on creating an HtmlHelper extension.  His extension was good, but did not use integrate with the FluentHtml model of MvcContrib, so I refactored his original into the following class, which does the same thing, but allows for fluent building of all the options.  Someone will undoubtedly point out that this could have used a couple of Enumerations, and their right, but I decided the API was static enough that I’d just create the methods. Anyway, I hope someone else gets some use out of this.

using System.Collections.Generic;
using System.Security.Cryptography;
using System.Web.Mvc;
using System.Web.Routing;
using MvcContrib.FluentHtml.Elements;
using System;
using System.Web;

public class Gravatar : Element
{
    private string _email;
    private string _default;
    private string _rating;
    private int _size;
    private string _alt;

    public Gravatar(string email) : base("img")
    {
        _email = email;
    }

    public Gravatar DefaultToUrl(string url)
    {
        _default = url;
        return this;
    }

    public Gravatar DefaultToIdenticon()
    {
        _default = "identicon";
        return this;
    }

    public Gravatar DefaultToMonsterId()
    {
        _default = "monsterid";
        return this;
    }

    public Gravatar DefaultToWavatar()
    {
        _default = "wavatar";
        return this;
    }

    public Gravatar DefaultTo404()
    {
        _default = "404";
        return this;
    }

    public Gravatar Size(int size)
    {
        if (size < 1 || size > 512) throw new ArgumentException("Gravatars can only be between 1 and 512 in size.", "size");
        _size = size;
        return this;
    }

    public Gravatar GRated()
    {
        _rating = "g";
        return this;
    }

    public Gravatar PGRated()
    {
        _rating = "pg";
        return this;
    }

    public Gravatar RRated()
    {
        _rating = "r";
        return this;
    }

    public Gravatar XRated()
    {
        _rating = "x";
        return this;
    }

    public Gravatar AlternateText(string alt)
    {
        _alt = alt;
        return this;
    }

    protected override TagRenderMode TagRenderMode
    {
        get
        {
            return TagRenderMode.SelfClosing;
        }
    }

    public override string ToString()
    {
        var src = string.Format("http://www.gravatar.com/avatar/{0}?", EncryptMD5(_email));

        if (!String.IsNullOrEmpty(_rating)) src += string.Format("r={0}&", HttpUtility.UrlEncode(_rating));
        if (_size != 0) src += string.Format("s={0}&", _size);
        if (!String.IsNullOrEmpty(_default)) src += string.Format("d={0}&", HttpUtility.UrlEncode(_default));

        base.builder.MergeAttribute("src", src);
        base.Attr("alt", _alt ?? "Gravatar");

        return base.ToString();
    }

    private static string EncryptMD5(string Value)
    {
        using(var md5 = new MD5CryptoServiceProvider())
        {
            byte[] valueArray = System.Text.Encoding.ASCII.GetBytes(Value);
            valueArray = md5.ComputeHash(valueArray);
            string encrypted = "";
            for (int i = 0; i < valueArray.Length; i++)
                encrypted += valueArray[i].ToString("x2").ToLower();
            return encrypted;
        }
    }
}

public static class GravatarHtmlHelper
{
    public static Gravatar Gravatar(this HtmlHelper html, string email)
    {
        return new Gravatar(email);
    }
}