Thursday, September 21, 2006
Hair pulling
So, installing Subversion took about 2 hours.
- Get the the Win32 binaries
- Install them on the server (just a test box for now)
- Get TortoiseSVN binaries
- Install them on the client
- Run the Subversion dedicated server (can't be bothered to install Apache)
- Point the client at the server
- Spend the rest of the morning importing some repositories and getting used to it
So then I think to myself "This really needs to be secure before it goes onto a public server with real source code." Looking at the documentation, I needed to setup SSH on the server. No hope! I spend about 10 hours going around in circles - none of the how-to's I could find were consistent with what actually happens.
Plan B. Install Apache. Configure it to work with Subversion. Job done. Took about an hour.
Right, now to secure it with SSL. Should be easy as the user community for Apache is even bigger than that for Subversion. Download a mod_ssl binary (Apache refuse to distribute the binary because of America's export laws). Was it easy? No! 3 days of hair pulling. Everything looks like it should work (I even recruited an Apache guru friend to check my configuration), but it falls over silently on boot. I was convinced it was some sort of problem with the keys or my configuration files.
You know how you get into a state of mind with a problem where you only look at a subset of possible solutions, and you try those repeatedly, even though you know that there are other options? I finally decided to remove everything and start again with a single binary distribution of Apache that included SSL. Suddenly, everything sprung into life.
Oh well. Works a treat now. I'm just waiting for the red-tape to part and allow me to buy a server for this. Kind of tricky to work together with a team 2,000 miles away without common source.
Friday, July 21, 2006
.NET XML Gotcha
XMLNode.SelectNodes() and XMLNode.SelectSingleNode() are very handy methods inside the DOM for jumping around inside XML documents. However, don't try to alter the nodes that are returned because they may not be live.It took me several hours to track down a bug in my code caused by this. I noticed that, although the OwnerDocument of the nodes returned was correct, when I walked back up the tree by following the parents, I bump into a null before reaching the document node.
Firstly, it amazes me to think that it must have taken effort to program it to be less useful. Secondly, I dislike the uncertainty of it all...
Quote from the Help:
The XmlNode should not be expected to be connected "live" to the XML document.
That is, changes that appear in the XML document may not appear in the XmlNode,
and vice versa.
Thursday, July 20, 2006
Foible #1
The short version is: You can't have a static abstract member.
The long version is...
I have written an extensible component. You add functionality (plug-ins) to it by writing additional assemblies and 'registering' them with the component.
The plug-ins must inherit from a public abstract class and I need them to implement their own version of a static property - we'll call it DataFormat.
I would like to implement it like this:
public abstract class MyBaseClass
{
public static abstract string DataFormat { get; }
// other stuff
}
But I can't! C# doesn't allow a member to be both abstract and static. So, I must remove one of those modifiers and keep the other, in order to compile.
If I keep the static modifier, i.e.
public abstract class MyBaseClass
{
public static string DataFormat
{
get
{
return "";
}
}
}
... then I cannot ensure that the inheriting object implements its own version.
If I keep the abstract modifier, i.e.
public abstract class MyBaseClass
{
public abstract string DataFormat { get; }
}
... then I need to create an instance of the object just to read a static value.
I originally took the first option, but it was painful. The reflection code was more complex and there was no early binding - you had to check at run-time that the object was written with a correct implementation of DataFormat.
So today I relented, and refactored to the second way. There's a lot less code, and it's strongly typed. I just have to instantiate the plug-in class when I need to read the DataFormat value.
This feels wrong, and yet I can't think of a better approach. Oh, and don't think Interfaces help, because they can't have static members.
Introduction
I am primarily a Delphi programmer by trade, having been programming that language since Delphi 1 back in the mid 90's. Previously I'd been a Pascal programmer, only dabbling in C a little as my University didn't teach it (shocking!).
At the time of creating this blog, I am concentrating on C# and learning my way around .NET, although I juggle both Delphi and C# in my day job. Actually, programming is only about half of my job these days, as I have to perform recruitment, mentoring and technical liaison duties - the price of career progression. But I never intend to stop programming (I'm sure a lot of people say that).
I plan to use this blog to document some of the technical foibles I come across, as both a memory aid and a possible resource for others.