The intersection of technology and leadership

Category: .Net (Page 2 of 2)

UK November Away Day

I’ve been lucky enough to attend two of Thoughtworks‘ Away Days over the last month. Most recently I attended the UK Away Day this weekend that provided a great opportunity to catch up with some people and generate some new ideas. I’d write up more about the Indian Away Day I’d attended two weeks prior, but running a two week training course almost immediately has taken away my time to reflect and my memory’s a little foggy these days.

Here’s an overview of the sessions that I attended:

  • A Lessons Learned session applying Ruby on Rails – An interesting session presented by Paul Ingles and George Malamadis about their approach to building a fully functional website with some of the pitfalls. I love these sorts of sessions as you get the insight into the decision making processes with talk about the constraints and thinking that pushed patterns into the direction of the end result. Really nice and a great topic to start leading into the Meta Programming session later than evening.
  • The Space Within – Hosted by the very calm Manoj Ramachadran who ran through a number of exercises to help improve the “quiet” times in our lives and give us an ability to become more effective. I found this interesting as it gave me insights into other methods to try.
  • Features of C#3.0 – Presented by Troy Gould and a great statement opening it along the lines of C#3.0 is included in .Net 3.5. How confusing is that? An interesting code example comparison by comparison of features new to C#3.0 introduced to support Linq. I think pretty much everyone was thinking how these features could be used effectively, and where they would be more likely (ab)used.
  • Case Study of a Consulting only session – An ever excitable and interesting co-presentation with Luke Barrett and one of our clients where the focus wasn’t directly about delivering working software, but focusing on delivering value even earlier by clarifying a business case and helping evaluate its feasibility. I enjoyed hearing the application of the same lo-fi techniques and methods bringing value in a different space for once.
  • Meta Programming – A fun session running through features of Meta Programming in Ruby by Farooq Ali and Julie Yaunches. I really enjoyed this session, and glad I could attend this since I’ve had the pleasure of working in the same room with both of these people and they’re passion for Ruby really shone throughout the presentation. They reminded me of the power language gives, and definitely helped me refine some thoughts I’d been having about the environment or approach needed to pull this off successfully.

I had a great time catching up with loads of people and had plenty of fun after the conference gathering at Sway.

Events, Reflection and how they don’t work in C#

Although the .Net reflection APIs make some tasks easier, we’ve found recently that those related to events and their delegates have been fairly poorly designed. Our task was very simple: dynamically manipulate the event handlers attached to a set of events.

It’s easy enough to get a declaration about an event of some sort using code like:

EventInfo infoAboutEvent = someObject.GetType().GetEvent("MyEvent"); 

Given your EventInfo class it’s easy to add an a new event handler. Unfortunately going the other way around ended up much harder. Unlike things like FieldInfo that give you direct access to get the field instance from the object using GetValue(owner), finding the event field isn’t as easy. First we had to look at all the fields, and filtered out things that looked like a Delegate so we could do some useful things with them, like finding out what subscribers were hooked up to our event.

Our ultimate goal of being able to dynamically remove EventHandlers at runtime further ran into problems when we were trying to unhook methods from private events. The result of trying to unhook a handler from a private event via the EventInfo.RemoveEventHandler method results in an InvalidOperationException with a message of “Cannot remove the event handler since no public remove method exists for the event.”

One more simple use of reflection and soon we were able to automatically unhook a variety of delegates from our events regardless of their access mechanism (although using code that wasn’t as nice as we wanted). A few refactorings later and we ended up with something actually quite useful in the end.

ReflectUtil.RemoveEventHandlersFrom(
 delegate(Delegate subject) { return subject.Method.Name.StartsWith("On"); }, 
  objectWithEvent);

And here’s the class that we ended up with. Although I can’t recommend people use reflection lightly, if you need to delve into the world of reflection with events, I hope you find this example useful.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

public sealed class ReflectUtil
{
  private static BindingFlags PrivatePublicStaticInstance 
    = BindingFlags.NonPublic | BindingFlags.Public |
      BindingFlags.Instance | BindingFlags.Static;

  public delegate bool MatchesOnDelegate(Delegate subject);

  public static void RemoveEventHandlersFrom(
    MatchesOnDelegate matchesOnDelegate, params object[] objectsWithEvents)
  {
    foreach (object owningObject in objectsWithEvents)
    {
      foreach (DelegateInfo eventFromOwningObject in GetDelegates(owningObject))
      {
        foreach (Delegate subscriber in eventFromOwningObject.GetInvocationList())
        {
          if (matchesOnDelegate(subscriber))
          {
            EventInfo theEvent = eventFromOwningObject.GetEventInfo();
            RemoveSubscriberEvenIfItsPrivate(theEvent, owningObject, subscriber);
          }
        }
      }
    }
  }

  // You can use eventInfo.RemoveEventHandler(owningObject, subscriber) 
  // unless it's a private delegate
  private static void RemoveSubscriberEvenIfItsPrivate(
    EventInfo eventInfo, object owningObject, Delegate subscriber)
  {
    MethodInfo privateRemoveMethod = eventInfo.GetRemoveMethod(true);
    privateRemoveMethod.Invoke(owningObject,
                               PrivatePublicStaticInstance, null, 
                               new object[] {subscriber}, CultureInfo.CurrentCulture);
  }

  private static DelegateInfo[] GetDelegates(object owningObject)
  {
    List delegates = new List();
    FieldInfo[] allPotentialEvents = owningObject.GetType()
      .GetFields(PrivatePublicStaticInstance);
    foreach (FieldInfo privateFieldInfo in allPotentialEvents)
    {
      Delegate eventFromOwningObject = privateFieldInfo.GetValue(owningObject) 
        as Delegate;
      if (eventFromOwningObject != null)
      {
        delegates.Add(new DelegateInfo(eventFromOwningObject, privateFieldInfo, 
          owningObject));
      }
    }
    return delegates.ToArray();
  }

  private class DelegateInfo
  {
    private readonly Delegate delegateInformation;
    private readonly FieldInfo fieldInfo;
    private readonly object owningObject;

    public DelegateInfo(Delegate delegateInformation, FieldInfo fieldInfo, 
      object owningObject)
    {
      this.delegateInformation = delegateInformation;
      this.fieldInfo = fieldInfo;
      this.owningObject = owningObject;
    }

    public Delegate[] GetInvocationList()
    {
      return delegateInformation.GetInvocationList();
    }

    public EventInfo GetEventInfo()
    {
      return owningObject.GetType().GetEvent(fieldInfo.Name, 
        PrivatePublicStaticInstance);
    }
  }
}

Upgrading from NHibernate 1.0.2 to 1.2.0.GA Experience Report

We recently upgraded to the latest version of NHibernate to make use of many of its new features. There are plenty of good reasons to upgrade including proper support of .Net 2.0, bug fixes, multi queries, new database dialects (including SQL Server 2005) and the ability to use generic types. We anticipated a few issues upgrading NHibernate, and though not the hardest upgrade ever, we did end up with a few more issues than expected. Here’s our experience upgrading to the latest version.

Things they warned you about

The NHibernate guys did a fantastic job writing their migration guide. They warned us that it wasn’t just simply a drop-in replacement and included a number of breaking API changes. Things that we found easy and had been documented included:

  • Updating our XML files from urn:nhibernate-mapping-2.0 to urn:nhibernate-mapping-2.2
  • Replacing outer-join="true" to fetch="join" and outer-join="false" to fetch="select"
  • Adding default-lazy="false" to each mapping file to deal with the change in default lazy loading behaviour
  • The HSQL count had been upgraded from an int type to a long type and our code had to cast it to the correct types
  • Deprecation of the CreateSQLQuery with parameters changed to ISQLQuery(String)

Things not on the label

  • Strange behaviour around the nosetter.camelcase access strategy – We had a property exposing a primitive type (string) of a more complex type, given the same field name and we kept getting a null result. It looked like it was trying to set the field using the type of the get property, even though the set should have been using the more complex user type. We fixed this by changing our mappings to field.camelcase instead of using the nosetter.camelcase.
  • SQL statement logging has changed – Our application listens very carefully to the Log4Net output that NHibernate generates, capturing each SQL statement and its parameters. Previous versions of NHibernate used to log their parameter values separately from their SQL statements, instead they are now logged on the single line. Thankfully our change was contained to two very small classes.
  • Replacing IClassPersister with IEntityPersister – We had to add a different constructor to our custom user types (also different from the current documentation), with a signature of PersistentClass model, ICacheConcurrencyStrategy cache, ISessionFactory required, IMapping mapping. Additionally we had to implement the new property Factory that came along with this interface. Now I had no idea where ISessionFactoryImplementor came from. Looking at the code, they had cast ISessionFactory in their constructor, and then returned that when the property Factory was called. It is a small inconsistency in their API that we ended up having to duplicate. This would be a problem if you ended up writing your own ISessionFactory but thankfully we haven’t done that ourselves. There were plenty more methods that we had to implement though none of them were actually very insteresting for the things that we had to do. Our solution: Cast ISessionFactory to ISessionFactoryImplementor and store it in the constructor just to be returned in the property.
  • IUserType Classes Disappearing – They had warned you that IUserType had moved into another namespace though I wasn’t quite clear what you had to do if you were using one of the old versions. In the end new Int16SqlType() is replaced by SqlTypeFactory.Int16, new Int32SqlType() by SqlTypeFactory.Int32, new Int64SqlType() by SqlTypeFactory.Int64, and new GuidSqlType() by SqlTypeFactory.Guid. I’m guessing it would be the same for any other IUserTypes you may be using.
  • IUserType New Methods – Four new methods appeared on the interface, GetHashCode, Replace, Assemble, Disassemble. Implementing GetHashCode we ended up delegating to our object, replace we delegated to using disassmemble then assemble, and implemented assemble and disassemble using DeepCopy, emulating what NHibernate Types do. It wasn’t really clear to me from documentation or upgrade guides what it should be
  • NHibernate.HibernateException : Could not instantiate cache implementation – It look like second level caching was now enabled by default and we hadn’t added configuration for it. We kept getting “Second-level cache is not enabled” messages. We disabled it and fixed this problem by explicitly turning it off. The property key is hibernate.cache.use_second_level_cache and turn it off by using the value false.

For the most part, considering how much of the core hibernate functionality had changed, we haven’t had too many issues although it’s still early days. We are noticing slightly different behaviour in the way that the flush semantics seem to be working (maybe auto flush mode is on by default now) though everything is still working quite pleasantly.

Announcing the Release of SharpZebra 0.90

Printing to the Zebra branded thermal transfer printers requires knowledge of their proprietary EPL2 language. Searching the net for a nice way of using EPL2 to communicate with these printers turns up a number of small projects, though none of them particularly ideal for integrating with a well written C# application, with most of them effectively getting you to copy and paste code into your project that you shouldn’t have to maintain.

Sharpzebra is a new open source project, written in C# that gives you access to a better printing API that abstracts away the EPL2 language concepts. I hope that it helps you spend more time putting together the things you need to print instead of working out how to print. See the Two Minute Quickstart here.

Download the binary release (dll), or binary with the project source code here.

Faster MSBuild Scripts – Convert ItemGroup to CreateItem

Speed, speed, speed… I wish MS tools would give me faster and faster feedback.

My lesson from last week – stay far away from ItemGroup elements in MSBuild files for most normal fileset equivalents (most especially if they only get used once). They are far better as CreateItem elements (though unfortunately only declarable within a Target element), taking almost the same syntax.

The result – instantaneous execution of any other targets outside of the one that uses these items, and a quicker ability to fail faster if you mistype the target name. Maybe it’s time to convert all of our targets to Nant?

Speeding up Visual Studio 2005

After working intimately with IntelliJ and Eclipse on previous projects, Visual Studio seems like such a beast for doing very simple things. Resharper makes it bearable though has a cost of its own. Our team has been playing around with trying to speed up the responsiveness. Here’s a few things we’ve tried that have worked at least most of the time:

  • Close the Toolbox tab – Even with just the tab closed, VS2005 still seems to use resources to keep it up to date. By removing it from your workspace, the project pane and other windows appear much more responsive.
  • Turn Off Animated Windows – When VS2005 gets sluggish, expanding and hiding tabs can appear horrendously slow as the screen repaints. Turning this option off helped a little bit. Uncheck the box found under Tools … Options … Environment … General … Animate Environment
  • Turn off the VS2005 File Navigator – With resharper installed, you don’t need VS2005 to update the list of methods and fields at the top of the file (CTRL-F12 does this nicely). I’ve hardly even noticed the small panel that sits at the top of the file you’re editing but apparently it takes quite a lot of effort for VS2005 to keep it up to date. Disable the Navigation Bar checkbox under Tools … Options … Text Editor … All Languages … Display.
  • Disable Startup Page – Wondered why VS2005 seemed sluggish on start up? It’s probably because it’s trying to download something from the Internet by default. Turn off the main startup page and the “live” content by unchecking the box found under Tools … Options … General … Startup … “Download content every”. I’d also change the “At Startup” option to “Show Empty Environment”.
  • Install Cool Commands – When you use Track Active Item in the Explorer pane, collapsing projects to run tests of various kinds can be hard. Cool Commands has some helpful things like Collapse All Projects so you don’t have to do it yourself when running tests.

I’d enjoy hearing anything else that anyone else may have tried to continue making VS2005 productive for you.

Dear Microsoft Connect Feedback

Thank you for responding to the issue that I raised (located here) about a problem how one of your ASP.Net 2.0 Framework controls and Internet Explorer (and only Internet Explorer) fail to work well together.

I’m very happy that the time that I spent detailing the steps to reproduce the problem was well spent and that, you too, were able to reproduce it. I’m quite disappointed that we have not made any progress on fixing the problem and the solution offered to me was to submit the same issue but against a different product group. Unfortunately it looks like that avenue is currently closed (see Internet Explorer feedback site)

As someone who has spent time giving you feedback that I feel will help make your overall product better, I find it a little shocking that you ask for me to commit even more time even though I do not feel like we have made any more progress to fixing the problem. I can understand your desire to ensure issues are properly classified so the appropriate team may address it, but I feel I do not need to be involved with your company’s strategy at issue resolution since I feel you have all the information you need.

I appreciate your constant correspondence to my submitted issue, but I think I would have had a much better experience had the person who closed my issue, reclassified, or even duplicated the issue for the correct team to ensure that continued progress is made on the issue. I don’t understand why I need to spend additional time iterating the same information I have already provided your company with.

I am happy to discuss more of my experience submitting feedback and my own personal thoughts on how the user experience could be better. I do encourage you to contact me (emailpat “at” thekua.com) as I will be happy to share more of my thoughts to help improve the experience.

Yours truly,

Patrick Kua

Visual Studio 2005 Annoyances

Anyone who has worked with me knows how much I enjoy working with mainly the keyboard alone. IntelliJ and Eclipse have great ways of doing things with the mouse, and as I’m finding out, Visual Studio has a plethora of them as well. Unfortunately many of them trigger hidden buttons or menu items that don’t exist. We accidentally turned on a “feature” of showing spaces as dots and took a while searching out how to turn if off as shown in the diagram below.

Visual Studio showing spaces as dots

If it ever happens to you, you apparently have to drag a button onto one of the menu bars in order to disable it. Otherwise try the short cut keys, CTRL-R followed by CTRL-W. Of course…

Getting NUnit ASP to work with .Net 2.0

On my current project we’ve been having a pretty good experience leveraging the NUnitASP library for automated testing of our website. In our second week of development, we noticed like many other people, that it is yet fully compatible with .Net 2.0 because of the way that ASP.Net now generates its javascript postback functions.

In the previous .Net version, ASP.Net seemed to generate a very simple function of the form of __doPostBack([targetId], [targetArguments]) that would effectively set two hidden variables (__EVENTTARGET and __EVENTARGUMENT respectively). In the current version, ASP.Net generates a much more complex javascript function (called WebForm_DoPostBackWithOptions) that I think is caused with use of any of the ASP validator components.

One work around that one person (Lance Ahlberg) found was to turn the “CausesValidation” property off for controls but this may or may not suit the way that you are developing your website. Looking at what the javascript generated does, I think that there must have been a better solution so I spent some time delving into the depths of NUnit ASP to find one.

The result is a patch to ControlTester.cs that allows the __EVENTTARGET and __EVENTARGUMENT to still be set by extracting out the appropriate values from the new WebForm_DoPostBackWithOptions javascript function. You can download the patch here but you have to build your own NUnit ASP, or wait until this is integrated with the next release. The ticket for my submission can be found here.

.Net 2.0 and IIS

I know this is old, but I’m putting up here as a note to myself… the installation order of IIS and .Net 2.0 matters. If you try running .Net 2.0 code on IIS that thinks it’s running a prior version of .Net (see the bottom part of the IIS error page to see what it is running), run the aspnet_regiis.exe /i command that sits deep in the bowels of the %windir%\Microsoft.NET\Framework\v2.0.50727 folder to make it run fine again.

Newer posts »

© 2024 patkua@work

Theme by Anders NorenUp ↑