At first glance, this seemed easy. Every object implements an interface called IPathWithObjectID, that specifies the object must have a property:
object ObjectID { get; }
Since ObjectID can be any object, it should be trivial to switch things to a string or something else.
The problem, however, lies in the details.
Most methods did this:
int ID = (int) MyObject.ObjectID;
At the time it seemed simple enough, but in hindsight, this is very limited.
A better approach would be to encapsulate the type cast into a method, which is what I refactored the code to do:
public int GetObjectKeyAsInt(IComparable ObjectKey) { if (ObjectKey != null) { if (ObjectKey is int) return (int)ObjectKey; throw new ArgumentException("The ObjectKey property is expected to be of type 'int'."); } throw new ArgumentException("The ObjectKey is null!"); }
Now, in reality all this method does is do a type cast, with some checks. But the power in it is later on I can refactor what is stored in the ObjectID.
So, my code goes from:
int ID = (int) MyObject.ObjectID;
To
int ID = GetObjectKeyAsInt(MyObject.ObjectID);
Maybe I want an ObjectID to be a new class called MyDataKey. Rather than changing hundreds of different places across the code base, I just change one. The GetObjectKeyAsInt method.
Methods provide a powerful mechanism of abstraction. Use them as often as possible, even if the action seems as trivial as a typecast.