Operator overloading your domain model with interfaces and base classes

One of the challenges in rewriting my online baseball game is dealing with enormous amounts of data that needs to be stored as aggregates, and coming up with a domain model and data mapping pattern that works. In this blog post, I’ll outline how I addressed some of those issues.

The Data Model

Baseball is very much a statistics-oriented game. Consider fielding statistics: putouts (PO), assists (A), errors (E) and others. These stats need to be stored:

  • Per game, for each player who played in the game, for each position he played (key fields: game, player, position)
  • Per season, for each player, for each team he played for, for each position he played (key fields: season, player, team, position)
  • Career, for each player, for each position he played (key fields: player, position)

On the database side, that results in three tables: GameFieldingStats, SeasonFieldingStats, and CareerFieldingStats. Each has the same set of fields to store the statistics (PO, A, and E); the differences are in the key fields for each, as outlined in the diagram below. (Note: For the remainder of this post, I’ll include only the first two of those tables to keep things short.)

. . . → Read More: Operator overloading your domain model with interfaces and base classes

Assess your .Net skills (and get a job) with this online test

Brant Estes of Magenic Technologies has just posted a very nice online quiz for .Net programmers. The test is there to pre-screen potential candidates to work at Magenic, but it’s also a very nice test for any .Net programmer to take (or to give to any .Net programmer you have considered hiring).

I took the test and scored a 75 out of 100 (without cheating, mind you), and was told I may make a great addition to Magenic. Unfortunately, I live in New York, and I’m not relocating. Besides, I just put in my resignation with my current employer so I can go back to independent consulting, so I’m not exactly on the market for full-time employment… but more on that . . .

→ Read More: Assess your .Net skills (and get a job) with this online test

A simple asp:Repeater replacement for simple needs

How many times have you had to parse through a collection of objects, outputting nothing more than a comma-delimited list of items in the result set. Typically, you’ll do this:

<asp :repeater runat="server">
<itemtemplate>Eval("Name")</itemtemplate>
<separatortemplate>, </separatortemplate>
</asp>

If you were parsing a list of states, it might look like this:

Alabama, Alaska, Arizona, Arkansas

There’s an easier way to handle these simple needs: create a CollectionToString() method. This method would accept an IEnumerable and, using reflection, read a property and return a delimited string. Of course, you choose the property and delimiter.

Note that we have two versions of this method: one which accepts an IEnumerable, the other which accepts an object. This is done to avoid the necessary typecasting in your code, since Eval() returns everything as an object.

public static string CollectionToString(IEnumerable collection, string property, string delimiter)
{
IEnumerator enumerator = collection.GetEnumerator();
if (enumerator == null || enumerator.MoveNext() == false)
return String.Empty;

Type type = enumerator.Current.GetType();
PropertyInfo propInfo = type.GetProperty(property);
if (propInfo == null)
throw new Exception(String.Format("Property '{0}' not found in collection", property));

StringBuilder output = new . . .

→ Read More: A simple asp:Repeater replacement for simple needs

A repository that works with multiple O/R mappers — is it possible?

A recent post on the WilsonORWrapper Google group talked about making WORW multi-database aware by removing static classes and singletons. Well, I’ve kind of been thinking of something similar lately…

For some time I have been toying with the idea of rewriting WORW to support a generic repository service that would work with any O/R mapper, much
like the logger and cache services work over different underlying libraries. By removing the static classes and singletons and adding a provider model for the O/R wrapper element, you would be able to instantiate multiple instances of a “Registry” class, a class which provides a set of services (Repository, Cache, Logger, etc.) based on a given configuration criteira.

As a test I wrote up a simple project (with unit tests!) as a proof-of-concept, using WORM and NPersist as underlying O/R mappers. The WORM part worked fine. The NPersist part almost worked — however, I believe the errors are related to using NPersist’s not-too-well-documented XML provider, . . .

→ Read More: A repository that works with multiple O/R mappers — is it possible?

Use reflection to compare the properties of two objects

In an update to WilsonORWrapper, I added a method which takes two objects of the same type and compares the properties of each, returning a value reflecting the results of the comparison. Any value other than zero would indicate that at least one property on the objects are not equal.

This method may have interest to people who don’t use WilsonORWrapper, so here’s an extracted version of the code that does the comparison.

using System;
using System.Reflection;

public static class ObjectHelper<t>
{
public static int Compare(T x, T y)
{
Type type = typeof(T);
PropertyInfo[] properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public);
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public);
int compareValue = 0;

foreach (PropertyInfo property in properties)
{
IComparable valx = property.GetValue(x, null) as IComparable;
if (valx == null)
continue;
object valy = property.GetValue(y, null);
compareValue = valx.CompareTo(valy);
if (compareValue != 0)
return compareValue;
}
foreach (FieldInfo field in fields)
{
IComparable valx = field.GetValue(x) as IComparable;
if (valx == null)
continue;
object valy = field.GetValue(y);
compareValue = valx.CompareTo(valy);
if (compareValue != 0)
return compareValue;
}

return compareValue;
}
}

With that, if you had a Name class in your code that had two properties, First and . . .

→ Read More: Use reflection to compare the properties of two objects