2005-11-30

JavaScript / CSS / DOM image magnifier

At first I wasn’t very impressed with this magnifying glass—I mean, who wants to view a pixelated portion of an image? Then I viewed the large, higher-density collage further down the page. When linking in and sizing down a larger picture, the magnified portion doesn’t become pixelated until you get to much higher magnifications.

I can imagine this being useful for maps and diagrams where both the overall layout and details are relevant. I’ve been thinking about large-scale software maps for years now—ever since I connected Isaac Asimov’s “Psychohistory” with flow charts and data flow diagrams.

This technique isn’t really the answer, since an image large enough to be truly useful would be slow to load and difficult to create and update. Instead, I’d like to see a similar technique applied to SVG.

In the mean time, it might be interesting to combine a Google Maps (tiled) approach with the magnifying glass technique, although the current code likely doesn’t support magnifying pieces of adjacent images.

2005-11-28

Cool sidewalk paintings

I wish I had the skill to do this.

2005-11-09

Framework Configuration

Evidently it’s not enough to install the redistributable for the .NET 2.0 framework if you want the Microsoft .NET Framework 2.0 Configuration control panel applet.

I don’t know why you would need to install an entire 345 MB SDK for the control panel applet when the 22 MB framework handles about everything else.

“About” I say, because InstallUtil.exe didn’t seem to install the Firebird provider in the GAC, although it reported success, and gacutil.exe reports missing MSVCR71.dll on Windows 2003 Server.

XCOPY it is…

Framework Configuration

Evidently it’s not enough to install the redistributable for the .NET 2.0 framework if you want the Microsoft .NET Framework 2.0 Configuration control panel applet.

I don’t know why you would need to install an entire 345 MB SDK for the control panel applet when the 22 MB framework handles about everything else.

“About” I say, because InstallUtil.exe didn’t seem to install the Firebird provider in the GAC, although it reported success, and gacutil.exe reports missing MSVCR71.dll on Windows 2003 Server.

XCOPY it is…

IIS 6.0 Manager for Windows XP

You may find this download useful so you don’t necessarily have to use Remote Desktop to administer IIS on Windows 2003 Server. It also seems to work on IIS 5.0 and 5.1.

2005-10-27

Shared Or Not?

Given these classes, which static members are shared?

class Base { public static int m_b; }
class Sub : Base { }
class GenA<T> : Base { public static int m_g; }
class SubGenA : GenA<int> { public static int m_sg; }
class SubSubGenA : SubGenA { }

Shared:

Base.m_b / Base.m_b
Base.m_b / Sub.m_b
Base.m_b / GenA<int>.m_b
GenA<int>.m_g / GenA<int>.m_g
GenA<int>.m_g / SubGenA.m_g
SubGenA.m_sg / SubSubGenA.m_sg

Not shared:

GenA<int>.m_g / GenA<string>.m_g
GenA<string>.m_g / SubGenA.m_g

I first tried for a truth table, but it got so big and hairy that I decided to simplify.

Why is this relevant? Because I need to share connections and transactions between classes in a controlled manner. That means sharing where I need to share and not sharing at other times. These class semantics determine what the language will do for me and what I must handle myself (and where).

These examples do not include the use of the [ThreadStatic] attribute. Presumably, the rules implied by the examples above would apply the same when marked with the [ThreadStatic] attribute, but only within a given thread. Members in other threads will have their own instance.

2005-10-21

threadvar for dotnet

I needed a global variable, of sorts. NActiveRecord, the ORM (object-relational mapping) library I’m creating, needs to be able to perform multiple database operations in a single transaction. This means I must either obtain a transaction handle and pass it around like a toke to every class and object that needs it—muddying layers and APIs and increasing fragility—or the classes need to be able to share a transaction handle behind the scenes, out of view of business logic.

However, ASP.NET is a multi-threaded environment and all manor of grief awaits the unwary—usually just after deployment to production—if proper respect is not paid to concurrency issues. What I needed was what Delphi calls a threadvar—a per-thread global variable.

I was midway through implementing a property that would store the current transaction handle in a static dictionary, indexed by the current thread’s ID—with a lock protecting it from being accessed simultaneously by multiple threads—when a slip of the fingers caused Visual Studio’s IntelliSense to pop up ThreadStaticAttribute. What’s this?

Online help tells me “A static field marked with ThreadStaticAttribute is not shared between threads. Each executing thread has a separate instance of the field, and independently sets and gets values for that field. If the field is accessed on a different thread, it will contain a different value.”

My implementation was reduced to:

[ThreadStatic]
protected static FbTransaction trans;

Nice.

2005-10-20

RTFM

Don’t make it any harder than it has to be—read the friendly manual.

I spent a little time trying to get some test cases working where the code depended on the .config file. Now, a typical unit test suite is library assembly—a .dll. As such, if you give it an app.config file, Visual Studio will not copy and rename it like it will for .exe’s. You must make that happen yourself. Since you don’t want to check in the bin/debug directory, you need to specify a “Pre-build event command line.”

copy $(ProjectDir)app.config $(ProjectDir)$(OutDir)$(TargetFileName).config

2005-10-18

Swifter than the average houseplant

My problem was that I needed a potentially large number of model classes to share a common base. The desired API has a rich set of static factory methods returning new instances. Downcasting a common base class all over the place is ugly, so these factory methods will preferably return the proper type.

In the past, this would have involved generating, either by hand or programmatically, a staggering number of methods. Donkey work. However, with generics, all this shouldn’t be necessary, right?

Now, up until now I have primarily used generics for containers and the like. In such cases the type and the generic class are orthagonal to each other. The type is declared class List and constructed List myList.

Subclassing and constructing generic types are both forms of specialization. However, since C# lacks mixins, this problem domain calls for both. At first, I didn’t think it would be possible. Then, I thought it would require two related classes, a model class and a factory class. I wanted the model class to have a singleton property referencing its corresponding factory class, but kept running into the same issues that were preventing me from solving the problem in a single class.

Finally, it occurred to me to try subclassing a constructed type while parameterizing the super (generic) type with the subclass: class Foo : Bar.

It works!

Example:


class NActiveRecord<T>
{
static T Find(int id) { ... }
static List Find(params int[] ids) { ... }
void Save() { ... }
}

class Account : NActiveRecord<Account>
{
...
string Name { get; set; }
...
}

void Main()
{
Account a = Account.Find(1);
Console.WriteLine(a.Name);
a.Name = "New Name";
a.Save();
List accounts = Account.Find(1,2,3);
foreach (Account b in accounts)
Console.WriteLine(b.Name);
}

2005-10-08

Ooh, this is nice!

Another helpful tip from Demetrius Nunes:

Drop the following method in your application_helper.rb file.


def stylesheet_auto_link_tags
stylesheets_path = "#{RAILS_ROOT}/public/stylesheets/"
candidates = [
"#{controller.controller_name}",
"#{controller.controller_name}_#{controller.action_name}" ]
candidates.inject("") do |buf, css|
buf <<>
"#{stylesheets_path}/#{css}.css")
buf
end
end

Next, drop <%= stylesheet_auto_link_tags %> in the of your layout file.

Now, if you have a controller foo, create a stylesheet called foo.css in public\stylesheets and it will automatically be linked to (but only if it exists) in all views rendered by that controller.

Likewise, if you have a style used only by action bar of controller foo, name your file foo_bar.css.

You will obviously want to make some styles global to a group of controllers or your entire application, but you can manage complexity and reduce unwanted interactions by scoping your stylesheets down this way.

2005-10-07

Ruby on Rails, HTML on Skids

Like Ruby, Rails “just fits”—at least if your mind works a certain way. However, my (lack of) HTML expertise is dragging me down.

I’m playing with Ajax and I discovered that one of the features doesn’t work quite like I thought it did. Specifically, when you specify the id of the element you want updated, the xhr (that’s Rails shorthand for XmlHttpRequest) results appear to update the InnerHTML. For my purposes, replacing the OuterHTML would be more convenient.

Why? Because, then I could replace an entire row of a table with the same template that I use to display it in the first place, without messy conditional code in the template or using nested templates.

For some purposes, using div’s or similar to display my tabular data might work as well and be more accepting of arbitrary nesting of elements within a row, but my poor CSS vocabulary makes any success at this purely accidental.

2005-09-29

A Tale of Two Types

Okay, the title was just too convenient to pass up, but this post is really a bit about nullable types and compatibility with .NET 1.1 code.

I was surprised to find that .NET 2.0 nullable types, when passed to code compiled by .NET 1.1, are not recognized as null, even when that library is being hosted by the 2.0 VM.

Now, I would not expect to be able to pass a nullable type into a 1.1 method expecting its non-nullable type without first casting it to that type. However, when passing it to a method expecting an object, I would expect it to be able to slide in just fine.

Not so.

int? i = GetInt("/foo/missingint");
Assert.IsTrue(i == null); // passes
Assert.IsNull(i); // fails

Changing int? i to object i didn’t work either. It may be that auto-boxed types—at least 1.1’s implementation—are incompatible with nullable types.

2005-09-16

Adventures in DotNet

Old Delphi hands won’t have to think twice about how to insert a literal (percent sign) in a Format statement—you double it of course (%%).

DotNet newbies, go with your gut and do the same thing in String.Format calls—double your { and } characters in formatting strings if you intend them as literals.

2005-09-15

Everything you know is wrong

You know how to access the configuration file from a DotNet app, right? You use System.Configuration.ConfigurationSettings.AppSettings, which is a static property that you index with a string.

However, if you’ve been around .NET 2.0 a little and have seen lists of feature changes in ADO.NET, you’re aware that there is now special support for connection strings. Books and websites will both tell you not to use ConfigurationSettings.AppSettings for connection strings anymore. Instead, you should use ConfigurationSettings.ConnectionStrings. This is the preferred way and possibly the only way if you’re trying to do fancy things like encrypt your connection strings or make your application database independent using provider factories.

Attempting this in Whidbey Beta 2 may cause you to doubt your intelligence and waste entirely too much time Googling websites that all have the same dated information and searching in local assemblies.

Beta 2, it turns out, has moved the functionality to ConfigurationManager.ConnectionStrings. Use something like ConfigurationManager.ConnectionStrings[“myalias”].ConnectionString.

And that’s life on the bleeding edge.