 |
|
|
 |
|
 |
I just found a great use for this Class
Storing SQL Queries
This allows me to store the Queries in the Class that Represents the Table
Public Class CallCust
Public Const _Connection As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & """C:\Aaron\Aarons DB SERVER.mdb"""
Enum CallCust
ID = 1
Name = 2
Type = 3
Address1 = 4
City = 6
Phone = 8
Zip = 15
End Enum
Public NotInheritable Class Query
Inherits Main.Mod_Enum.StringEnumeration(Of Query)
Private Sub New(ByVal StringConstant As String)
MyBase.New(StringConstant)
End Sub
Public Shared ReadOnly WHERE_City As New Query("Select Name as Name, Type as Type, Address1 as Address1, City as City, Zip as Zip, Phone as Phone FROM CallCust WHERE City LIKE ")
Public Shared ReadOnly WHERE_Type As New Query("Select Name as Name, Type as Type, Address1 as Address1, City as City, Zip as Zip, Phone as Phone FROM CallCust WHERE Type LIKE ")
Public Shared ReadOnly WHERE_Zip As New Query("Select Name as Name, Type as Type, Address1 as Address1, City as City, Zip as Zip, Phone as Phone FROM CallCust WHERE Zip LIKE ")
End Class
End Class
This is Extremely Helpful but Sadly it lacks the Ability to Select a StringEnumeration from a List like you could with a normal Enum
Public sub Test(IsEnum as CallCust.CallCust)
|
|
|
|
 |
|
 |
hello.
Thank you for the class.
I have some remarks:
0) Exception Throwed when:
Public Class Form1
Private NotInheritable Class DbTableName
Inherits StringEnumeration(Of DbTableName)
Public Shared ReadOnly Roulement As String = "PARAM_GRAPHIQUE_ROULEMENT"
Public Shared ReadOnly Habillage As String = "PARAM_GRAPHIQUE_HABILLAGE"
Public Shared ReadOnly Theorique As String = "PARAM_GRAPHIQUE_THEORIQUE"
Public Shared ReadOnly Vehicules As String = "PARAM_GRAPHIQUE_VEHICULES"
Private Sub New(ByVal StringConstant As String)
MyBase.New(StringConstant)
End Sub
End Class
Private CurrentDbTableName As DbTableName
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.CurrentDbTableName = DbTableName.Habillage
At this point I get an exception:
in
Friend Shared Function GetSharedFields() As StringEnumeration(Of TStringEnumeration)()
on the line:
Dim myField As StringEnumeration(Of TStringEnumeration) = CType(myFieldInfo.GetValue(Nothing), StringEnumeration(Of TStringEnumeration)) 'Shared Fields use a Null object
Message (sorry for french)
Impossible d'effectuer un cast d'un objet de type 'System.String' en type 'WindowsApplication1.StringEnumeration`1[WindowsApplication1.Form1+DbTableName]'.
1) Warning. Use the good comments (comments with "&" symbols are underlined)
''' <summary>
''' Base Class for String Enumerations.
''' Fully Represents an Enumeration using Strings.
''' Automatically casts *and* compares to Strings.
''' </summary>
/serhio
|
|
|
|
 |
|
 |
Hi Serhio -
This is a very simple fix, not a bug. Please try this:
Private NotInheritable Class DbTableName
Inherits StringEnumeration(Of DbTableName)
Public Shared ReadOnly Roulement As New DbTableName("PARAM_GRAPHIQUE_ROULEMENT")
Public Shared ReadOnly Habillage As New DbTableName("PARAM_GRAPHIQUE_HABILLAGE")
Public Shared ReadOnly Theorique As New DbTableName("PARAM_GRAPHIQUE_THEORIQUE")
Public Shared ReadOnly Vehicules As New DbTableName("PARAM_GRAPHIQUE_VEHICULES")
Private Sub New(ByVal StringConstant As String)
MyBase.New(StringConstant)
End Sub
End Class
Glad you're finding the class useful! Thanks for checking in...
Ryan
|
|
|
|
 |
|
 |
"I still prefer my little base class because it does not require a manager class or a dictionary / hash lookup; it mimics an enumeration almost perfectly. This way, my developers won't even know the difference."
There is one imortant way in which the StringEnumeration doesn't seem to mimic the behaviour of a normal Enum, which is the way it is handled by Intellisense, unless I'm missing something. One of the nice things about normal Enums is that as soon as you try to set or test the value of a variable of that type as you are coding, intellisense pops up with the possible values of the enum. When I try this with your ProductType example, it doesn't happen.
Also, en Enum's basic data type is an integer, and you can set an integer variable directly to the value of an enum, but although the underlying datatype of the StringEnumeration is conceptually a string, you cannot set a string variable to ProductType.FifthWheels, you have to say ProductType.FifthWheels.ToString.
As for the idea of using a dictionary to translate the Enum values to text strings, that would be dependent on correctly maintaining the dictionary - if you were to add a value to the Enum, but forget to add it to the dictionary, there is nothing that would trap this error at compile time, which seems quite fragile to me. It also implies that every time you need to use the dictionary lookup, you would have to code error-handling in case the dictionary element is not found.
Just some observations.
|
|
|
|
 |
|
 |
Hi Zeleks -
Thanks for the quality written response. Appreciate it.
- Intellisense -
Admittedly - it's not 100% perfect. When you are setting a variable to one of your StringEnumeration values - Intellisense does not show you all your enumeration options automatically. Yes, this is a weakness with what I have here. Though, to get Intellisense to kick-in - all you need to do is type the name of your enumeration (ProductType.) and Intellisense instantly shows you your enumeration options.
- .ToString -
Can you please elaborate on this? You should not need to use .ToString to either upcast a string to a StringEnumeration or downcast your StringEnumeration to a string. I modified the code here a couple days ago to add & implement upcasting w/ generics. Please copy & paste the new code here & verify you no longer have this problem.
Thanks again for giving it a try & posting your feedback!
Ryan D. Hatch
|
|
|
|
 |
|
 |
Hi Ryan
I agree the intellisense thing is a minor point, it's just that I love the way normal Enums work in this regard - when passing parameters to a function for example, as soon as you reach the parameter that is an enum, the possible values pop up - but I admit it's a very minor niggle!
As for upcasting to a string:
Dim A As String = ProductType.FifthWheels
I've taken the latest version of your code, and what I've found is that the above works fine if the statement is in the same assembly where "ProductType" is defined, but the same statement in another assmbly gives me "Option Strict On disallows implicit conversion from 'SomeAssembly.ProductType' to 'String'. ??
Your solution is the best I've found so far, so thanks!
|
|
|
|
 |
|
 |
Hi Zeleks -
Thank you very much for your feedback. I've updated the code & it now supports Option Strict On. Widening operator was needed instead of Narrowing.
Much thanks for using the code! Hope I've been helpful -
Ryan D. Hatch
PS. If I find a solution for the Intellisense, I'll be sure to let you know!
|
|
|
|
 |
|
 |
Hi Ryan, thanks for that, I can now reference it directly as a string, without having to append ".ToString".
I did come across another situation though, where I still needed to add .ToString, sorry! If I try to do a string concatenation using "&", of two of the StringEnum values:
Dim A As String = ProductType.FifthWheels & ProductType.MotorHomes
I get:
"Overload resolution failed because no accessible & is most specific for these arguments".
Thanks for your work on this.
|
|
|
|
 |
|
 |
Hi Zeleks -
Thanks for reporting the bug. Fixed!
Ryan
|
|
|
|
 |
|
 |
In order to use the term Enumeration, wouldn't there need to be some sort of collection to enumerate? I think your base class would need to include some kind of function in which you could loop through each item.
|
|
|
|
 |
|
 |
Hi Sike -
It does. See above: ProductType.Enum.GetNames and ProductType.Enum.GetValues
To answer your question, the reason each element of the StringEnumeration is also a StringEnumeration - is to ensure that you can pass a StringEnumeration element to methods - the exact same way do for normal Enumerations. This keeps your enumerations down to a single Type which you can easily pass around to your methods.
I have the compatibility down very, very close to a standard Enumeration. Hope this helps!
Ryan D. Hatch
|
|
|
|
 |
|
 |
I agree with PIEBALDconsult. I don't see any reaons to use this. At least, that couldn't be done using simpler methods anyway.
|
|
|
|
 |
|
 |
Dave,
You're a smart guy - Would you please elaborate on handling String enumerations in a simpler way, as you have recommended here?
Please advise. Much Thanks!
Ryan D. Hatch
|
|
|
|
 |
|
|
 |
|
 |
Hi Piebald,
String Enumerations can help when working with different data sets you don't have control over. I have migrated several databases (medical, insurance, manufacturing, etc.) from old legacy systems to new solid schemas in SQL Server, MySQL, & others. Many legacy systems use strings as Primary and Foreign keys.
String Enumerations allow me to set these string constants in code (primarily for look-up tables) and work with strongly-typed objects, as opposed to using error-prone quoted strings all throughout my code.
I investigated several methods for string enumerations a few years ago and was not pleased with my options. Thus, I developed this for internal use out of necessity. It's not going to fly you to the moon. [wink] However, it does work very well & is all I have ever needed. Your first link uses the exact same solution (a base class which supports casting); I had not seen that article when I did my initial research. Glad we all found a common solution!
Thanks for the links!
Ryan
modified on Wednesday, February 18, 2009 9:34 AM
|
|
|
|
 |
|
 |
But why do you need it? Simply to avoid using ToString? What does this provide that an enumeration doesn't?
|
|
|
|
 |
|
 |
Hi PIEBALD,
I apologize, I did not originally understand your question. String enumerations are a must when you run into constants (ie, lookup tables) that cannot otherwise be used as normal variable names in .NET Enumerations.
As I mentioned earlier - if you do any work with legacy systems, Microsoft Excel integration, or inherit just poorly designed database schemas - you will likely need String Enumerations. A few examples might include: enumerations that have scalar/mixed types (Strings, Numbers, etc.), strings that include spaces, special characters, or strings that begin with numbers, etc. And yes - I have run into these scenarios. The need for String Enumerations arises when you cannot name a regular enumeration variable in .NET using these special characters. For instance, a simple example would be - I cannot do:
Enum Test
Fifth Wheel
End Enum
Obviously, .NET will not allow you to use spaces as variable names. Yet, I need to match this string verbatim in the database (including the space). This String Enumeration class allows me to bridge the real-world string constants being used with acceptable .NET variables I can use throughout my code.
Hope this helps you understand my needs for the String Enumeration class. It has worked well for me, and I thought I would share.
Thanks & Take care!
Ryan D. Hatch
modified on Sunday, February 22, 2009 11:42 PM
|
|
|
|
 |
|
 |
Have you considered using a Dictionary? I've done that a few times:
System.Collections.Generic.Dictionary<string,Campers> dic =
new System.Collections.Generic.Dictionary<string,Campers>() ;
dic [ "Fifth Wheel" ] = Campers.FifthWheel ;
System.Console.WriteLine ( dic [ "Fifth Wheel" ].ToString() ) ;
But I much prefer using my EnumTransmogrifier, which hides the details of that and centralizes the maintenance to the enumeration:
enum Campers
{
[System.ComponentModel.DescriptionAttribute("Fifth Wheel")]
FifthWheel
}
PIEBALD.Types.EnumTransmogrifier<Campers> campers =
new PIEBALD.Types.EnumTransmogrifier<Campers>() ;
Campers x = campers.Parse ( "Fifth Wheel" ) ;
switch ( x )
{
case Campers.FifthWheel :
{
System.Console.WriteLine ( campers.ToString ( x ) ) ;
break ;
}
}
In my opinion, if you want an enumeration you need to start with an enumeration. If you want to be able to refer to members of that enumeration by other names, then use a Dictionary to map those other names.
If you simply want to constrain possible input strings then I suggest a HashSet:
System.Collections.Generic.HashSet<string> valid =
new System.Collections.Generic.HashSet<string>() ;
valid.Add ( "Fifth Wheel" ) ;
if ( valid.Contains ( "Fifth Wheel" ) )
{
System.Console.WriteLine ( true ) ;
}
|
|
|
|
 |
|
 |
Hi PIEBALD -
Thanks for your GREAT response!
Very ingenious solutions you have there. Your Transmogrifier is very, very interesting. Essentially, it's a manager class for your enumerations, which accesses Attributes via Reflection. Very cool!
It's great to know everyone has their own solution that fits them best. I still prefer my little base class because it does not require a manager class or a dictionary / hash lookup; it mimics an enumeration almost perfectly. This way, my developers won't even know the difference.
Thanks again for your wonderful reply. Much appreciated!
Ryan D. Hatch
PS. We are using the LLBLGen Pro & VisualWebGUI frameworks here. Having good luck with them both.
|
|
|
|
 |
|
|
 |