Monday, March 15, 2010

Landfile Transfer Notes

Although we are not quite finished with the CMS project, we are now double-dipping into the Landfile Transfer project. I wanted to make some notes in case I forget what I've done...

First time I attempted to build the existing Phase I Landfile project, there were cwbx.dll reference errors, "The system cannot find the file specified." I had originally referenced the cwbx.dll in place in the IBM folder in Program Files, but now I want to put the dll in the lib directory of the project so I stop losing it. I copied the dll there and made a reference in the project, but got the error that it wasn't a valid dll. So I had to make an Interop for it using tblimp from the Visual Studio command prompt. I renamed the original dll cwbx.org.dll so that I could call the interop assembly cwbx.dll and not have to change the Imports statements in the code before I even started coding again. The build then succeeded.

Friday, March 12, 2010

Code Smells

Stumbled on this great little page listing code smells and possible fixes.

Friday, March 5, 2010

The Rules Engine and the Command Engine

I ran into a little issue the other day...

The CMS application I am working on needed a URL builder, which combined a root directory, an optional subdirectory, and a file name. Aspects of the URL must be validated after construction, such as not allowing invalid characters.

I created two CmsUrl engines - one that processes commands, and one that processes rules. The command engine required a concrete object, since the commands modified the URL. However, this became an issue because ICommand demands an Execute method with no parameters and no return value. Therefore, the only way to get my URL string into the Command is in the constructor. Additionally, command executing cannot return a value, so the command must be acting on a reference or global string of some sort. Right? (I read a post somewhere [StackOverflow?] that said simulating reference pointers in C# was accomplished by passing a reference to the containing object, which got me to thinking on different terms.)

In most situations, I think of commands as acting on a data store. The command encapsulates all information needed to make a change on the data store. The data store exists outside the command, obviously, but the command knows how to get to it and modify it. When it comes to strings, they are usually passed by value. To relate it to the data store example, it would be like copying the entire database into the command for modification.

Well, what I ended up doing was Dependency Injection - injecting the engine into the command, and the engine holds the URL to be modified. The command then acts on the URL in the engine. The Process method on the engine has an output parameter which returns the modified URL (correct extension added to the file, etc). That seemed to simulate the data store example.

With the Rule engine, it's only job is the throw Exceptions if the rules aren't met. There is no modification of the string. So it was implemented as a static class. I don't know if that was right or not, to make one static and the other concrete, but that's what I did...

Thursday, March 4, 2010

Generic Interface Interesting-ness

I wanted to set up a generic extension method that would bind a Repeater to the type T Items that I passed in. The definition was:

public static void bind_with<T>(this Repeater repeater,INavigation<T> navigation)
{
if(navigation.Items.Count() > 0)
{
repeater.DataSource = navigation.Items;
repeater.DataBind();

}

}


So obviously, T has to have the Items collection. My interface looked like this:

interface INavigation<T>
-- IEnumerable<T> Items

My Navigation classes (TopNavigation and SideNavigation) already had the Items collection, so I just tacked the interface on to the class declaration, and it passed the compilation test.

Now for the interesting part... when I cast the input to the correct type, I do not have to use the generic method signature as it is redundant. So I call the method like this:

bind_with((SideNavigationItem)e.Item.DataItem)

The method casts SideNavigationItem to INavigationItem<SideNavigationItem>, which has the collection of Items<SideNavigationItem>. No need to use the generic signature.

But even further still, I can also use this:

bind_with((SideNavigation)e.Item.DataItem)

which implements INavigation<SideNavigationItem>, and is also cast the same way. The type parameter defines the type of the Items collection, so it works both ways. I was also able to use:

bind_with(site.SideNavigation).

Cool!

I overloaded the method in order to use it with CmsPage.Articles collection, which is not INavigation at all. I guess I could use interface ICmsCollection, and then have only one method, but I don't know...