NAnt Task to Enforce VB.NET Project Settings
July 7th, 2005

Here is a NAnt task I am using to enforce VB.NET project settings during a build. This is useful if you can’t use <vbc> to compile your projects.

Usage example:

<vboptions compare="Binary" strict="true" explicit="true"
    path="${projectfile}"
    if="${path::get-extension(projectfile) == '.vbproj'}" />

The code:

/// <summary>
/// Enforces specific VB settings on a particular project.
/// </summary>
[TaskName("vboptions")]
public class VbOptionsTask : Task
{
    private string _path;
    private bool _strict;
    private bool _explicit;
    private string _compare;

    [TaskAttribute("path", Required=true)]
    public string Path
    {
        get { return _path; }
        set { _path = value; }
    }

    [TaskAttribute("explicit", Required=false)]
    public bool Explicit
    {
        get { return _explicit; }
        set { _explicit = value; }
    }

    [TaskAttribute("compare", Required=false)]
    public string Compare
    {
        get { return _compare; }
        set { _compare = value; }
    }

    [TaskAttribute("strict", Required=false)]
    public bool Strict
    {
        get { return _strict; }
        set { _strict = value; }
    }

    private bool CheckOption(string opt, bool val)
    {
        bool on = (string.Compare(opt, "On", true) == 0);
        return (on == val);
    }

    private void ValidateOption(XmlNode node, string attr, bool val)
    {
        XmlAttribute a = node.Attributes[attr];
        if(a == null || !CheckOption(a.Value, val))
        {
            throw new BuildException(
                 string.Format("The build option '{0}' in project {1} is not set to '{2}.'",
                     attr, this.Path, (val ? "On" : "Off")
                     )
                 );
        }
    }

    protected override void ExecuteTask()
    {
        XmlDocument proj = ProjectFactory.LoadProjectXml(this.Path);
        if(proj == null)
        {
            throw new BuildException("Could not load project xml for: " + this.Path + ".");
        }
        XmlNode settings = proj.SelectSingleNode("//VisualBasic/Build/Settings");
        if(proj == null)
        {
            throw new BuildException(this.Path + " is not an Everett .vbproj file.");
        }
        XmlAttribute c = settings.Attributes["OptionCompare"];
        if(c == null || string.Compare(c.Value, this.Compare, true) != 0)
        {
            throw new BuildException(string.Format("The project {0} does not have Option Compare set to {1}.", this.Path, this.Compare));
        }
        ValidateOption(settings, "OptionStrict", this.Strict);
        ValidateOption(settings, "OptionExplicit", this.Explicit);
    }

    public VbOptionsTask()
    {
        _compare = "Binary";
        _explicit = true;
        _strict = true;
    }
}

DataSetSurrogate Remoting Sink
July 4th, 2005

I have received a trickle of requests for some code that I have written and alluded to here and here: namely, a custom Remoting sink that swaps DataSets for DataSetSurrogates as they pass by.

Unfortunately, it would not be legal for me to release this code. Sorry. However, I think I can give a general outline of it without giving away the farm.

The first thing I should say is that the cure for your remoting performance woes is probably not the DataSetSurrogate in every case. (Review what I have said here and here for more information).

If it’s at all practical, my recommendation to you is to simply avoid using DataSets in n-tier situations.

Still here? Great.

Ok, with the disclaimers out of the way, the code works in two pieces: the remoting sinks and the ISerializationSurrogate. The serialization surrogate is relatively easy to implement, if you’ve gotten this far.

The sinks are a little more clever. I wanted to continue using the framework BinaryFormatter sinks, since they added a lot of things to the mix that I didn’t feel like re-implementing.

However, there’s no way for you to modify how the BinaryFormatterClient/Server sinks do their serialization. More explicitly, there’s nowhere to plug in the ISerializationSurrogate object that you’ve written.

The client and server sinks actually pull-the-old-switcheroo on the messages coming through the pipe. That’s the clever bit.

So I am leaving the framework sinks there, but altering the messages that go through them. The messages they see have a binary representation of the “real” messages appended as a parameter.

That’s the fastest way to write the sinks. If you implement complete formatter sinks, you can accomplish it a little more efficiently.

Hope this helps. Sorry that I can’t be more specific. If you’ve gotten this far without your head exploding, trust me, you’re smart enough to write these classes.

Anyway, the result is significantly faster for many kinds of data. Not for all kinds of data.


The Mandelbrot Set Meets Rapid Development Tools
July 3rd, 2005

The first time I wrote this program, it was a DOS-based program. I wrote my own putpixel routine in x86 assembly for it (among other things). It took me a few sleepless nights to finish writing it.

Today I got bored and wrote it again. It took less than a half hour this time.

Closeup of the Mandelbrot Set

Somehow, it was more satisfying the first time.