Thursday, November 23, 2006

Today I have recieved a comment on my article on Optimizing Rendered Page Size, that it is not possible to override the LoadPageStateFromPersistenceMediummethod of a Page class because it is marked as internal in ASP.NET 2.0. Strange thing was that I have made just that in one of the projects I have been working on with ASP.NET 2.0! So I went for some searching.

First thing I have checked the code to see if it really compiles with the override - it did. There is even a support from Intelisense for overriding this method. Next I want to see if the is LoadPageStateFromPersistenceMediummethod really internal. Using reflector I have been able to confirm this. It really is "protected internal virtual". So the question is: how am I able to override it?

The reason we are able to override such a method is that "protected internal" is an OR relationship which means that such a member is accessible in the types that derive from our type AND in all types defined in the assembly. This should make it clear why we are able to override this method.

What may be less clear is why overriding "protected internal" requires sometimes "protected override" instead of "protected internal override". If you read once more the definition, it clearly states that protected internal is accessible to sub-types and the assembly. So if you want to override a method in the same assembly you would use "protected internal override". If on the other hand you want to override this method in other assemblies you must not use the "internal" access modifier because it would make the method visible to every type in your assembly - which would in fact change the visibiliti of the method. This would of course result in an error from the compiler. In this case you would get the CS0507 error.

I hope this sheds some light on the issue.

kick it on DotNetKicks.com

Thursday, November 23, 2006 2:15:34 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  | 

Following my last article on IComparable vs IComparer interfaces I now present a common pattern that I have found to be very effective in terms of code usability.

In order to make working with IComparer implementing classes more natural and intelisense friendly I usually create the inner classes of the main class and expose the objects as as static properties or methods. The following example demonstrates:

public class Person
{
  int age;
  string name;
  public static IComparer<Person> GetPersonAgeComparer()
  {
    return new PersonAgeComparer();
  }
  public static IComparer<Person> GetPersonNameComparer()
  {
    return new PersonNameComparer();
  }
  private class PersonAgeComparer : IComparer<Person>
  {
    #region IComparer<Person> Members
    public int Compare(Person x, Person y)
    {
      return x.age.CompareTo(y.age);
    }
    #endregion
  }
  private class PersonNameComparer : IComparer<Person>
  {
    #region IComparer<Person> Members
    public int Compare(Person x, Person y)
    {
      return x.name.CompareTo(y.name);
    }
    #endregion
  }
}

Now when you need to sort a collection of Person objects you just get the right IComparer from the Person's static Get*Comparer methods. Notice that the IComparer classes are defined as private so the only way to create them is through the factory - like static method. Making the classes private is nice a way to prevent Intelisense from unnecessary displaying them when what we really need is the concrete object. Notice the use of generic interface, which is new to the .NET Framework 2.0. You could also use the partial classes feature to put the comparers in a separate file if necessary.

kick it on DotNetKicks.com

Thursday, November 23, 2006 1:25:33 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, November 22, 2006

In .NET some of the collection types such as Array, ArrayList, List<T> expose the Sort method that allows you to sort the collection. In order for those classes to sort the collection, there has to be a way for them to somehow compare objects with each other. The most basic Sort method usually does not require any arguments other than the collection itself in case of the static Array.Sort. In this case how does the framework know how to compare our objects? Is person1 greater than person2? Or maybe they are equal?

Enter the IComparable interface. By implementing this interface, the objects of the type become, as the name suggest, comparable, so now it is possible to compare person1 to person2 using a simple person1.CompareTo(person2) call. With this each Sort method can easily handle sorting. An example implementation of sort method is included in the MSDN documentation.

So what is wrong there? If you take a Int32 objects, a String object, the IComparable interface on those is pretty straightforward and self explaining. It is plain even to a non-technical person that 1 < 3 and "abc" = "abc". But what about a more complex types such as a custom Person type that represents a person in the real world.

What does it mean for one persons to be greater (or equal for that matter) than the other? It does not mean anything without a context, a criteria by which we compare the two. So for example if were to compare the age of both persons, we would be able to say if who is older (greater) or younger (lesser). We could compare their names, their salary or whatever, but we need to know the criteria before we start.

Suppose that we have a class definition of Person as follows:

public class Person : IComparable
{
  int age;
  string name;

What does it mean for an object of this class to be comparable to each other? Is the name used? Or maybe the age? The fact that we don't know! The only way to know is to check the documentation or the implementation of the CompareTo method. First one goes against the rule I like to follow that states that the code should be self documenting. In this case it isn't. The second option breaks the rule of encapsulation - that is, we have to know the implementation of an object to work with it. Fortunately there is another way to compare and sort objects.

Enter the IComparer interface. This interface allows you to compare two objects in a similar way the IComparable interface does. The difference here is that it IComparer allows for much greater expressiveness. An implementation of IComparer is always a class which does have a name. This name explains (or at least it should) exactly what it does. For example:

public class PersonAgeComparer : IComparer

Makes it obvious to everyone what will be the criteria for the comparison without breaking the encapsulation. This makes your code easier to understand and much more self documenting. I strongly discourage everyone from using the IComparable interface on classes where it is not explicit what would be compared, even if it will be the only comparison made.

kick it on DotNetKicks.com

Wednesday, November 22, 2006 7:48:06 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, November 09, 2006

The standard procedure when working with ASP.NET Web Projects looks more or less like this:

1) Open/Create a solution in Visual Studio
2) Add/Change some of the pages/code in the solution
3) Press F5 to build and run the project to see the effect of the changes

This procedure has its pros and cons. The main advantage is that we get a debugger support from the IDE, so in case of an exception, we have the possibility to see what and where went wrong. We can also step through the code and see what is being done step by step. Those are only the few of many good things the Visual Studio gives you. 

So what are the drawbacks of this standard procedure? Take for example a page which requires you to login before you can use it. Using the Visual Studio to run the browser you have to login every time you start the debug session. You can somehow work around this problem by creating a persistent cookie (remember me checkbox) so that you will not have to login every time. But what if you have to login using different user name and password? Providing logout button returns you to the original problem. The bigger problem is however with multi-step, wizard-like operations. If you have a 5 steps in your Wizard and something goes wrong on the last step, you have to close the browser to stop debugging (ASP.NET does not support the edit and continue feature with the standard Web Project). Then after making the required changes you have to start the wizard all over again.
Keep in mind that those are only simple examples to illustrate the problems and benefits of the standard approach. They are in no way complete.

Now, We know that there are problems and there are benefits of the "standard way" but there is another way that I'm sure most ASP.NET developers coming from backgrounds such as PHP know about and use a lot. This solution was the only possible way to test and debug your web applications if you had no debugger support from your IDE - like was the case few years ago and I'm not sure if it is still the case. Basically what you do is run your own browser and navigate to the page that Visual Studio would otherwise navigate to using the browser it has started. Now you can browse through the pages and test whatever you want and in case something goes wrong, you can just make the changes in the Visual Studio and recompile. It is possible since the IDE is not in the debugging state while you do this. (The scope of the changes may cause the running application to reload causing you to relogin, but this will not always be the case)

What we don't get with the alternative way of working with our pages is the debugger support, so now if something goes wrong we will get the error page instead of the break in the debugger. Fortunately you can always attach Visual Studio to a running process hosting ASP.NET and debug the application as usual. After you have found the error you can safely stop the debugger and you browse window will not be closed. Also you will not suffer from the startup time of required fro Visual Studio to start the browser and the debugger. This way instead of the edit and continue you can work with a save and refresh style.

I'm not saying that the second approach is better or worse. I'm only pointing out that in some cases there is a faster way to do things, especially when you are getting irritated by the Internet Explorer's address bar always remembering the wrong addresses :-).

kick it on DotNetKicks.com

Thursday, November 09, 2006 8:56:04 AM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
 Wednesday, November 01, 2006

There is a refactoring feature in Visual Studio 2005 that lets you generate method stubs for methods that don't exists yet. I have described this feature in my article on how implementing MembershipProvider can help to understand the Test Driven Development (TDD) rule of writing your tests first. Basicaly the feature I'm talking about generates a stub for a method and puts "throw new Excelption("The method or operation is not implemented.")".

As powerful and helpful as this feature is, there is a problem with it! It throws an Exception and not a more proper NotImplementedException as would be expected. We can change that!

The snippet responsible for generating method stubs is located in the Visual Studio installation folder. By default it is something like: "c:\Program Files\Microsoft Visual Studio 8\VC#\Snippets\1033\Refactoring\MethodStub.snippet". Changing the original value of:

 <Function>SimpleTypeName(global::System.Exception)</Function>

to

<Function>SimpleTypeName(global::System.NotImplementedException)</Function>

While searching for the solution to method stub problem I have also found that there is a "PropertyStub.snippet" file which should be used to generate property stubs. However I have been unable to find a way to invoke this snippet (it is not the same as "prop" snippet"). I have made a search on google and found some discussion on Microsoft's site that property stubs are not supported because it is hard to inferr something from their usage. Strangely enough there are tools such as Resharper that allow you to generate such stubs and why would there be a snippet file?

kick it on DotNetKicks.com

Wednesday, November 01, 2006 4:12:51 PM (Central European Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |