EDN Admin
Well-known member
Ive been working on a class library, called "Handy", that contains a number of custom objects designed to facilitate a particular piece of .Net functionality or fill a gap in what I consider common coding requirements. Some of these classes arose out of my own needs, and others from threads on these forums. One is the result of a sub-issue on another CodePlex project.
Im considering making a CodePlex project for the entire solution, but first Id like to get some general feedback on design and usage. Ive posted the compiled debug DLL onSkyDrive. I would be willing to make the source code available to select community contributors with whom I am familiar. If you are interested in the source code, please contact me using reedkimble at live dot com. When/if the solution is published to CodePlex, the entire source code will be available to the public.
Here is a rundown of the namespaces and classes in the Handy library:
HANDY.COLLECTIONS
ConcurrentDataBank
Represents a generic collection of multiple types. Key-value pairs of objects are stored in unique internal type dictionaries. The collection is manipulated with generic Get(Of T) and Set(Of T) methods allow storage of multiple types within a single container. This DataBank is backed by ConcurrentDictionary objects and so is thread-safe.
DataBank
Just like the ConcurrentDataBank, but backed by a normal Dictionary and so not thread-safe. I have another version of this class which fully implements serialization (providing all contents are serializable), and plan to later add that functionality to this version of the class.
DictionaryList
Represents a generic dictionary of TKey and TValue pairs, where the values are actually stored in an List(Of TValue). Standard IDictionary(Of TKey, TValue) members return the first item in a value list. Additional methods are provided for accessing the entire list of keyed values.
SearchableStringCollection*
Represents a binary string dictionary which is a collection of strings stored in a character dictionary array. At the cost of additional memory usage, this class is extremely fast at collection modifications and searches regardless of the number of items in the collection. Strings can also be found using partial matches similar to the String.StartsWith() method.
SearchableStringDictionary
Just like the SearchableStringCollection, only implemented as a generic dictionary. So the key will always be a string, but you can supply an type T for the values.
SequentialBuffer
Represents a generic sequence of elements which is written to and read from independently. The buffer can also be fixed size, can grow, or can wrap. The collection maintains independent read and write index values so you can add to the collection and later read from it sequentially, much like a stream.
* Special thanks to CrazyPennie for an example binary dictionary implementation.
HANDY.IO
BufferStream
This is essentially a SequentialBuffer implemented specifically for the Byte data type that also inherits from System.IO.Stream. So it is a class that acts as both a collection and a stream for byte data which can be written to and read from independently. And can be fixed size, grow, or wrap on overrun.
CsvWriter
We have a nice TextFieldParser, but nothing to generate delimited text files. So thats what this simple class does. It opens a file stream and then provides methods to write individual fields or complete records to the file.
FileEncryption
Provides static methods for simple AES file encryption using a SHA encoded password and optional custom IV data.
Ftp
Provides static methods for simple FTP file transfer. I have to admit that the methods may not be immediately intuitive, but they are simple once understood.
HANDY.IO.SERIAL
SerialDevice
Represents a wrapper for the SerialPort which offers its own secondary thread to automatically receive incoming data and then process it via assigned delegates. So you can create a SerialDevice instance with given serial port configuration info and then set properties for a "is message complete" and "process message" delegate which are simple functions you write to check the received data and process it when you determine that youve received a complete message (or per byte if you so desire, yeah theres added overhead versus doing it yourself, but it still performs fairly well).
HANDY.MATH
Circle*
Represents a circle given a center point and radius, and provides common helper properties and methods.
Fraction
Represents a numerical fraction in both decimal and numerator/denominator terms.
This is something from the past on the forums... Im not sure it ever was perfect, but this version works pretty well with reasonable limitations (the only issue revolving around the convert from decimal feature - the rest of the structure is fine).
Geometry*
Contains common geometric calculations along with a little bit of physics help. I still dont know why some of these functions arent standard in .Net on the PointF structure...
Line
Represents the line segment formed by two two-dimensional vectors, and provides common helper properties and methods.
Range
Generates an array of numbers. Yes, Enumerable.Range() works fine for single ranges of integers. This class offers an overloaded static Get() method which accepts multiple start-stop pairs. So rather than specify a start and a count, you specify a start and a stop number. If the start is bigger than the stop, the range will decrement. Some overloads also allow you to specify the step of the increment or decrement.
Vector2*
Represents a two-dimensional vector of Single values. This structure needs to exist simply because SizeF and PointF are a pain to work with when doing calculations LOL. Having to convert one to the other to satisfy certain method arguments has always been a pet-peeve of mine in .Net. This structure fixes that and supplies common helper properties and methods.
* These classes originally came from the GDI Gaming API, but these implementations may vary from the originals.
HANDY.TASKS
TaskWorker
Encapsulates a System.Threading.Task providing cancelation, timeout, progress reporting, and completion notification. The class works by simply providing Action(Of TaskWorkerState) delegate methods to the TaskWorker.Create() static factory method. The "do work" delegate is the only required argument, but you can also supply methods to be executed for progress reporting and when the worker ends. Additional overloads allow you specify the number of iterations of work to perform and a control to sync progress reports and completion notifications against. There is also a ConcurrentDataBank included for simple data transfer between threads. This makes simple multithreading very easy, and I think its generally better than a BackgroundWorker. But this is also a class that Id really like to see put through its paces and have some other threading experts look at.
HANDY.TEXT
CString
Provides the ability to declare "C-like" string literals which parse standard "C" slash-notation. I posted a feedback thread on this class a while back and it was shown that the class itself may not really be necessary. However, Ive kept it as a container for the functionality. After additional feedback, this functionality may be refactored into a shared method.
NumericStrings
Converts integer and decimal values into their textual string representations. I looked at a number of routines for doing this and though I came up with a rather unique approach using an Enum. This is implemented as a static class but there are shared properties for customization. The final formatting of the output is subject to change based on feedback.
SafeStringBuilder
Similar to a StringBuilder, this class treats Chr(0) as an "EmptyCharacter" and cannot throw index out of range exceptions. This makes it very easy to modify the contents of the string without constantly checking to ensure that your target index is within bounds. The class also offers a number of additional helper methods and can be cast to and from a String.
TextAnalysis
This class offers static methods which implement the Metaphone I and Damerau-Levenshtein Distance algorithms. Metaphone is one I played with for my own curiosity, Damerau-Levenshtein came from these forums. This class uses the SafeStringBuilder and was the reason for its creation.
HANDY.EXTENSIONS
Finally there is a module offering a couple of shared methods and then a number of extensions for Handy objects as well as a few CLR types such as IEnumerable(Of T).ToRandomList, Stopwatch.ToMillisecondsString, and IEnumerable(Of Byte).ToHexString among others.
So thats the contents of the library as it currently stands. Most (not all) of the classes and class members contain summary comments at a minimum, and most of the objects should be fairly straightforward to use. I will also try to post a few usage examples of some of the objects.
Please feel free to use this thread to discuss the library or report bugs. All constructive comments are welcome.
Reed Kimble - "When you do things right, people wont be sure youve done anything at all"
View the full article
Im considering making a CodePlex project for the entire solution, but first Id like to get some general feedback on design and usage. Ive posted the compiled debug DLL onSkyDrive. I would be willing to make the source code available to select community contributors with whom I am familiar. If you are interested in the source code, please contact me using reedkimble at live dot com. When/if the solution is published to CodePlex, the entire source code will be available to the public.
Here is a rundown of the namespaces and classes in the Handy library:
HANDY.COLLECTIONS
ConcurrentDataBank
Represents a generic collection of multiple types. Key-value pairs of objects are stored in unique internal type dictionaries. The collection is manipulated with generic Get(Of T) and Set(Of T) methods allow storage of multiple types within a single container. This DataBank is backed by ConcurrentDictionary objects and so is thread-safe.
DataBank
Just like the ConcurrentDataBank, but backed by a normal Dictionary and so not thread-safe. I have another version of this class which fully implements serialization (providing all contents are serializable), and plan to later add that functionality to this version of the class.
DictionaryList
Represents a generic dictionary of TKey and TValue pairs, where the values are actually stored in an List(Of TValue). Standard IDictionary(Of TKey, TValue) members return the first item in a value list. Additional methods are provided for accessing the entire list of keyed values.
SearchableStringCollection*
Represents a binary string dictionary which is a collection of strings stored in a character dictionary array. At the cost of additional memory usage, this class is extremely fast at collection modifications and searches regardless of the number of items in the collection. Strings can also be found using partial matches similar to the String.StartsWith() method.
SearchableStringDictionary
Just like the SearchableStringCollection, only implemented as a generic dictionary. So the key will always be a string, but you can supply an type T for the values.
SequentialBuffer
Represents a generic sequence of elements which is written to and read from independently. The buffer can also be fixed size, can grow, or can wrap. The collection maintains independent read and write index values so you can add to the collection and later read from it sequentially, much like a stream.
* Special thanks to CrazyPennie for an example binary dictionary implementation.
HANDY.IO
BufferStream
This is essentially a SequentialBuffer implemented specifically for the Byte data type that also inherits from System.IO.Stream. So it is a class that acts as both a collection and a stream for byte data which can be written to and read from independently. And can be fixed size, grow, or wrap on overrun.
CsvWriter
We have a nice TextFieldParser, but nothing to generate delimited text files. So thats what this simple class does. It opens a file stream and then provides methods to write individual fields or complete records to the file.
FileEncryption
Provides static methods for simple AES file encryption using a SHA encoded password and optional custom IV data.
Ftp
Provides static methods for simple FTP file transfer. I have to admit that the methods may not be immediately intuitive, but they are simple once understood.
HANDY.IO.SERIAL
SerialDevice
Represents a wrapper for the SerialPort which offers its own secondary thread to automatically receive incoming data and then process it via assigned delegates. So you can create a SerialDevice instance with given serial port configuration info and then set properties for a "is message complete" and "process message" delegate which are simple functions you write to check the received data and process it when you determine that youve received a complete message (or per byte if you so desire, yeah theres added overhead versus doing it yourself, but it still performs fairly well).
HANDY.MATH
Circle*
Represents a circle given a center point and radius, and provides common helper properties and methods.
Fraction
Represents a numerical fraction in both decimal and numerator/denominator terms.
This is something from the past on the forums... Im not sure it ever was perfect, but this version works pretty well with reasonable limitations (the only issue revolving around the convert from decimal feature - the rest of the structure is fine).
Geometry*
Contains common geometric calculations along with a little bit of physics help. I still dont know why some of these functions arent standard in .Net on the PointF structure...
Line
Represents the line segment formed by two two-dimensional vectors, and provides common helper properties and methods.
Range
Generates an array of numbers. Yes, Enumerable.Range() works fine for single ranges of integers. This class offers an overloaded static Get() method which accepts multiple start-stop pairs. So rather than specify a start and a count, you specify a start and a stop number. If the start is bigger than the stop, the range will decrement. Some overloads also allow you to specify the step of the increment or decrement.
Vector2*
Represents a two-dimensional vector of Single values. This structure needs to exist simply because SizeF and PointF are a pain to work with when doing calculations LOL. Having to convert one to the other to satisfy certain method arguments has always been a pet-peeve of mine in .Net. This structure fixes that and supplies common helper properties and methods.
* These classes originally came from the GDI Gaming API, but these implementations may vary from the originals.
HANDY.TASKS
TaskWorker
Encapsulates a System.Threading.Task providing cancelation, timeout, progress reporting, and completion notification. The class works by simply providing Action(Of TaskWorkerState) delegate methods to the TaskWorker.Create() static factory method. The "do work" delegate is the only required argument, but you can also supply methods to be executed for progress reporting and when the worker ends. Additional overloads allow you specify the number of iterations of work to perform and a control to sync progress reports and completion notifications against. There is also a ConcurrentDataBank included for simple data transfer between threads. This makes simple multithreading very easy, and I think its generally better than a BackgroundWorker. But this is also a class that Id really like to see put through its paces and have some other threading experts look at.
HANDY.TEXT
CString
Provides the ability to declare "C-like" string literals which parse standard "C" slash-notation. I posted a feedback thread on this class a while back and it was shown that the class itself may not really be necessary. However, Ive kept it as a container for the functionality. After additional feedback, this functionality may be refactored into a shared method.
NumericStrings
Converts integer and decimal values into their textual string representations. I looked at a number of routines for doing this and though I came up with a rather unique approach using an Enum. This is implemented as a static class but there are shared properties for customization. The final formatting of the output is subject to change based on feedback.
SafeStringBuilder
Similar to a StringBuilder, this class treats Chr(0) as an "EmptyCharacter" and cannot throw index out of range exceptions. This makes it very easy to modify the contents of the string without constantly checking to ensure that your target index is within bounds. The class also offers a number of additional helper methods and can be cast to and from a String.
TextAnalysis
This class offers static methods which implement the Metaphone I and Damerau-Levenshtein Distance algorithms. Metaphone is one I played with for my own curiosity, Damerau-Levenshtein came from these forums. This class uses the SafeStringBuilder and was the reason for its creation.
HANDY.EXTENSIONS
Finally there is a module offering a couple of shared methods and then a number of extensions for Handy objects as well as a few CLR types such as IEnumerable(Of T).ToRandomList, Stopwatch.ToMillisecondsString, and IEnumerable(Of Byte).ToHexString among others.
So thats the contents of the library as it currently stands. Most (not all) of the classes and class members contain summary comments at a minimum, and most of the objects should be fairly straightforward to use. I will also try to post a few usage examples of some of the objects.
Please feel free to use this thread to discuss the library or report bugs. All constructive comments are welcome.
Reed Kimble - "When you do things right, people wont be sure youve done anything at all"
View the full article