# Sunday, April 15, 2007
I just wrote my first Mono c# program, talk about easy.  The hardest part was figuring out how to invoke the mono c# compiler, and no its not csc, but mcs.  Mono can be installed from the Ubuntu "Add Applications" applet, but its actually easier and more direct to install it from the shell:

sudo bash
apt-get install mono mono-gmcs


Once Mono is installed you may want to install a text editor or MonoDevelop.  I just installed a text editor, called Cream, which actually picked up the syntax highlighting which surprised me.  Anyway I preceded to put together helloworld.cs in my home directory:

using System;

namespace SNeal
{
    public class HelloWorld
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World, from Ubuntu!");
        }
    }
}

Then from the shell again:

mcs helloworld.cs

Which produced helloworld.exe which can then be run (very similar to Java in this respect) by typing:

mono helloworld.exe


That's all there is to it!  Further things I plan to try out on Ubuntu with Mono: Generics, ASP.NET, NUnit, MonoDevelop, and Eclipse (which is my favorite IDE).

Sunday, April 15, 2007 6:41:21 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
Now this is what I consider a good morning:



Virtual Server 2005 R2 with Visual Studio Orcas CTP and VMWare with Ubuntu for other dev...
Sunday, April 15, 2007 3:57:07 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# Friday, April 13, 2007
I really don't understand why Spring and thus Spring.NET chose to default all objects or beans to singleton scoping.  I mean why?  In my experience singletons are rare magical beasts that usually only exist because they act as a sort of service locator.  When I use any plain old C# object I have to use the new keyword.  I'm comfortable with the new keyword, and would seriously miss it if all my classes were forced to be singletons right out of the box.  You can think of the code that you write as the blueprints for constructing a new instance at runtime, well I think that should apply to the XML you use to wire objects up in Spring with - blueprints for new objects, not singletons!  Instead the designers of Spring chose to default to singleton prototyping so that every object I declare in my XML config only ever exists once.  This is a serious scoping mismatch especially when writing something stateless like a web application where you want new instances for each request.

Why am I ranting about this anyway?  I ran into a very subtle state bug where I forgot to set singleton="true" on one of my ASP.NET controller objects, so each request was using the same controller class instance.  This may explain another error that the testers were getting at times: Request is not available in this context.

IoC
Friday, April 13, 2007 9:45:39 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# Wednesday, April 11, 2007
There may be a time you need access to the current executing ASP.NET handler's (page) view state without having a reference to the executing page.  I did today while creating a view state adapter that is injected into my page controllers.  I swapped out the Session adapter for this new ViewState adapter in my Spring.NET config.

Here's the code where I grab a view state reference in the adapter:

return ((PageBase)System.Web.HttpContext.Current.Handler).PageViewState;

Basically I grab the current handler and cast it to PageBase type.  In my application all pages inherit from PageBase, and PageBase exposes a public PageViewState property.  This allows me to grab the viewstate without having a direct reference to the page instance.  Some of this extra work is required because the System.Web.UI.Page ViewState property is not public, but protected.

Wednesday, April 11, 2007 8:53:47 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, April 06, 2007
Before running NAnt that uses the P4Edit NAntContrib task ensure that you go into P4Win and from the menu select Settings | Use Current as Default.  Without doing this you may run into an error message that [some file] - must refer to client '[client name]'.

Ant
Friday, April 06, 2007 9:16:52 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
I'm not sure hardware currently supports this, but it would be really cool if there was a web browser GPS control, header - or something to that effect.  Basically the idea is to be able to perform a search through your web browser that uses your GPS location as one of the search parameters.  This would be incredibally useful for handheld internet devices.  My navi in my truck already does this when I need to find a gas station, bank, or restaurant nearby.  Handheld browsers should be able to do the same without the user needing to manually input a GPS coordinate.  Think realestate listings.  You're driving down a nice neighborhood and you want to search for all listed houses within 3 miles, with GPS coords this would be a snap.  What if you are standing inside a store?  You could go directly to the store's web site just because you are physically standing inside it.  I think people would really dig this - I know I would.  What about location aware internet advertising?  This is just the tip of the iceberg, especially once everyone has a phone that also acts as an internet connectivity device.

Friday, April 06, 2007 5:46:32 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, March 27, 2007
I have finally come to the realization that my mindset, beliefs, programming methodology, and above all my spirit are incompatable with my current employer.  I need to work for IT company again.

WTF
Tuesday, March 27, 2007 9:59:20 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# Thursday, March 22, 2007
"ctl00___ctl00___ctl00_ctl00_bcr_ctl00___Comments___Comments_ctl06_NameLink" Why do you mock me?!  Why do you make something so blatantly easy, so cumbersome and impossibly difficult?  Its for my own protection you say?  I can't be trusted you say?

Clearly when MS brought out ASP.NET they never  really intended for programmers to do client side programming, because its too difficult for Mort to even understand the difference between client side code versus server side code.  I've explained the difference to Mort several times, however I still don't think he truly understands the difference.  I blame the leaky abstraction that is ASP.NET for making it too difficult for Mort to truly understand what's really happening under the hood of ASP.NET.

Thursday, March 22, 2007 4:36:28 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, March 19, 2007
For no real good reason I decided to implement another reusable IComparer, this time using .NET 2.0 and generics.  My focus this time was on:
  • Better API using generics.
  • SQL compliant ordering clause.
  • Multi-property sort ordering.

GenericComparer<Address> comparer = new GenericComparer<Address>()
   .OrderBy("FirstName, LastName DESC");

As you might guess this IComparer will sort a collection of Address objects by FirstName and then by LastName descending.  The code could still use some cleaning up and I plan on replacing all of the reflection calls using lightweight code generation, but nonetheless it does pass my current set of tests.

public class GenericComparer<T> : IComparer<T>
{
    Type declaringClassType = typeof(T);
    IList<PropertyOrderBy> properties = new List<PropertyOrderBy>();

    /// <summary>
    /// Default ctor instantiates a new GenericComparer instance.
    /// </summary>
    public GenericComparer() { }

    public GenericComparer<T> OrderBy(string sqlOrderBy)
    {
        string[] parts = sqlOrderBy.Split(',');
        foreach (string part in parts)
        {
            string[] orderbyParts = part.Trim().Split(' ');
            string fieldName = orderbyParts[0].Trim();
            string direction = string.Empty;

            if (orderbyParts.Length > 1)
                direction = orderbyParts[1].Trim();

            properties.Add(new PropertyOrderBy(fieldName, direction));
        }

        return this;
    }

    private IComparable GetPropertyValue(object instance, string propertyName)
    {
        // This won't work if the property is overloaded by type
        PropertyInfo info = declaringClassType.GetProperty(propertyName);
        object val = info.GetValue(instance, null);

        IComparable retVal = val as IComparable;
        if (retVal == null)
        {
            throw new ApplicationException(
             propertyName +
             " Type must implement IComparable to be able to use a PropertyComparer.");
        }

        return retVal;
    }

    #region IComparer<T> Members

    public int Compare(T lhsObj, T rhsObj)
    {
        int result = 0;

        foreach (PropertyOrderBy orderBy in properties)
        {
            IComparable lhs = GetPropertyValue(lhsObj, orderBy.PropertyName);
            IComparable rhs = GetPropertyValue(rhsObj, orderBy.PropertyName);

            if (orderBy.SortDirection == "DESC")
                result = rhs.CompareTo(lhs);
            else
                result = lhs.CompareTo(rhs);

            if (result != 0)
                return result;
        }

        return result;
    }

    #endregion    

    private class PropertyOrderBy
    {
        public string PropertyName;
        public string SortDirection = "ASC";

        public PropertyOrderBy(string propertyName, string direction)
        {
            direction = direction.ToUpper();
            if (direction != "ASC" && direction != "DESC" && direction != string.Empty)
                throw new ArgumentOutOfRangeException("direction", "Unknown order by direction: " + direction + ", expected either ASC or DESC.");

            if (direction != string.Empty)
                this.SortDirection = direction;

            this.PropertyName = propertyName;
        }
    }
}

Monday, March 19, 2007 6:37:10 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, March 18, 2007
For whatever reason when I cut and paste code into DasBlog using the "Insert Code" feature, my tabs always end up missing - even though they initially show up right after clicking Parse Code.  I ended up having to find and replace all blocks of four spaces with a tab before pasting into DasBlog.

The missing tab problem and the fact the syntax highlighting isn't as nice as Visual Studio 2005 makes me think I should start looking for another tool to format my code snippets that appear in this blog.

Sunday, March 18, 2007 7:02:58 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |