I've been looking at writing an exercise app, and this would require some kind of units of measure for distance (as well as time).
I could use an enum to represent the different types of units - metres, kilometres, yards, miles etc. But this seems to be lacking from the point of view of converting between the different types - I would need a class to represent the conversions. What I want is a more integrated approach - the use of static read-only properties.
What I want to be able to do is best described by the following test:
The Measurement struct is very simple, a couple of properties - Amount & Unit and a ConvertTo method:
As you can see in the ConvertTo method the Unit class owns the conversions - it is more than just a simple Enum - it has behaviour, how to convert between the different units of measure.
So how are the units defined?
A Unit instance is exposed as a read-only static property on a static Units class:
What makes this approach interesting is the use of the Lazy<T> to get around the circular reference problem when the static properties are initialized - for example the Centimetre properties uses the Metre & Kilometre properties which in turn use the Centimetre property, which in turn use the Metre & Kilometre properties.
As you can see this could go on for ever if I didn't use the Lazy<T> inside the Unit class. It allows me to disconnect the creation of the conversions from the Converters property because by the time the Converters properties is accessed the constructor on the Unit class will have completed.
The smart bit of code is inside the Converters property, a pretty standard piece of lazy initialization to create the actual Converter instances.
The code above is from the Simple.Units repo available on GitHub
I could use an enum to represent the different types of units - metres, kilometres, yards, miles etc. But this seems to be lacking from the point of view of converting between the different types - I would need a class to represent the conversions. What I want is a more integrated approach - the use of static read-only properties.
What I want to be able to do is best described by the following test:
The Measurement struct is very simple, a couple of properties - Amount & Unit and a ConvertTo method:
As you can see in the ConvertTo method the Unit class owns the conversions - it is more than just a simple Enum - it has behaviour, how to convert between the different units of measure.
So how are the units defined?
A Unit instance is exposed as a read-only static property on a static Units class:
What makes this approach interesting is the use of the Lazy<T> to get around the circular reference problem when the static properties are initialized - for example the Centimetre properties uses the Metre & Kilometre properties which in turn use the Centimetre property, which in turn use the Metre & Kilometre properties.
As you can see this could go on for ever if I didn't use the Lazy<T> inside the Unit class. It allows me to disconnect the creation of the conversions from the Converters property because by the time the Converters properties is accessed the constructor on the Unit class will have completed.
The smart bit of code is inside the Converters property, a pretty standard piece of lazy initialization to create the actual Converter instances.
The code above is from the Simple.Units repo available on GitHub
Comments
Post a Comment