From: Captain Jack on 10 Mar 2010 16:10 Kinda stumped on this one... I've got a generic class, defined like this: Public Class GenClass(Of VType As IComparable) Inherits BaseClass [ ... ] End Class The class works just fine, no problems with it. I'm going to build a list of objects of this type at run time, from a table in a database that corresponds to the properties of GenClass. I've got a code in the database that identifies what VType should be for each instance (for example, 1 would be "String", 2 would be "Integer", and so on). So far, so good. What I can't quite figure out is how to create an instance at run time of the the generic class with a Type object, or anything else. I've looked at the ConstructorInfo and Activator classes, and I'm either not seeing it, looking in the wrong place, or trying to do it the wrong way. I'm getting by right now with a Select Case statement, explicitly naming the type, something like this (stripped of all but the essential code for this example): [... Function receives Rdr, a SqlClient.SqlDataReader ...] Dim ObjectList As New List(Of BaseClass) Do While Rdr.Read Dim ValueCode As Integer = Rdr("ValueCode") Select Case ValueCode Case 1 : ObjectList.Add(New GenClass(Of String)) Case 2 : ObjectList.Add(New GenClass(Of Integer)) et cetera ... End Select Loop This works, but seems clunky to me. However, I can't figure out a better way of doing it. Anyone have any ideas they'd like to share? :-) Thanks, Jack
From: Armin Zingler on 10 Mar 2010 16:18 Am 10.03.2010 22:10, schrieb Captain Jack: > Kinda stumped on this one... I've got a generic class, defined like this: > > Public Class GenClass(Of VType As IComparable) > Inherits BaseClass > [ ... ] > End Class > > The class works just fine, no problems with it. I'm going to build a list of > objects of this type at run time, from a table in a database that > corresponds to the properties of GenClass. I've got a code in the database > that identifies what VType should be for each instance (for example, 1 would > be "String", 2 would be "Integer", and so on). So far, so good. > > What I can't quite figure out is how to create an instance at run time of > the the generic class with a Type object, or anything else. I've looked at > the ConstructorInfo and Activator classes, and I'm either not seeing it, > looking in the wrong place, or trying to do it the wrong way. > > I'm getting by right now with a Select Case statement, explicitly naming the > type, something like this (stripped of all but the essential code for this > example): > > [... Function receives Rdr, a SqlClient.SqlDataReader ...] > Dim ObjectList As New List(Of BaseClass) > Do While Rdr.Read > Dim ValueCode As Integer = Rdr("ValueCode") > Select Case ValueCode > Case 1 : ObjectList.Add(New GenClass(Of String)) > Case 2 : ObjectList.Add(New GenClass(Of Integer)) > et cetera ... > End Select > Loop > > This works, but seems clunky to me. However, I can't figure out a better way > of doing it. Anyone have any ideas they'd like to share? :-) The association between the number (1, 2, etc) and the type is determined by yourself, right? So I don't see another way but this Select Case statement. -- Armin
From: Captain Jack on 11 Mar 2010 14:44 "Armin Zingler" <az.nospam(a)freenet.de> wrote in message news:OZoJ7QLwKHA.4196(a)TK2MSFTNGP02.phx.gbl... > Am 10.03.2010 22:10, schrieb Captain Jack: >> This works, but seems clunky to me. However, I can't figure out a better >> way >> of doing it. Anyone have any ideas they'd like to share? :-) > > > The association between the number (1, 2, etc) and the type is determined > by yourself, right? So I don't see another way but this Select Case > statement. Yeah... I was toying with the idea of maybe storing the name of the type in the database though. So, instead of 1 or 2, I'd store String or Integer (or maybe Int32 if that made more sense). I could get the type by name from the current assembly, but I just don't have a clue how to create an instance of the class, even if I have a Type variable set the proper value. -- Jack
From: Mark Hurd on 12 Mar 2010 09:20 "Captain Jack" <CaptainJack1024(a)comcast.net> wrote in message news:_tKdnQt1w8KPlwXWnZ2dnUVZ_vidnZ2d(a)giganews.com... > Kinda stumped on this one... I've got a generic class, defined like > this: > > Public Class GenClass(Of VType As IComparable) > Inherits BaseClass > [ ... ] > End Class > > The class works just fine, no problems with it. I'm going to build a > list of objects of this type at run time, from a table in a database > that corresponds to the properties of GenClass. I've got a code in the > database that identifies what VType should be for each instance (for > example, 1 would be "String", 2 would be "Integer", and so on). So > far, so good. > > What I can't quite figure out is how to create an instance at run time > of the the generic class with a Type object, or anything else. I've > looked at the ConstructorInfo and Activator classes, and I'm either > not seeing it, looking in the wrong place, or trying to do it the > wrong way. > > I'm getting by right now with a Select Case statement, explicitly > naming the type, something like this (stripped of all but the > essential code for this example): > > [... Function receives Rdr, a SqlClient.SqlDataReader ...] > Dim ObjectList As New List(Of BaseClass) > Do While Rdr.Read > Dim ValueCode As Integer = Rdr("ValueCode") > Select Case ValueCode > Case 1 : ObjectList.Add(New GenClass(Of String)) > Case 2 : ObjectList.Add(New GenClass(Of Integer)) > et cetera ... > End Select > Loop > > This works, but seems clunky to me. However, I can't figure out a > better way of doing it. Anyone have any ideas they'd like to share? > :-) > > Thanks, > Jack You need to know two things: 1. GetType can reference generic types by including Of with out a type name. E.g. GetType(GenClass(Of)) 2. Type.MakeGenericType(T) is the runtime equivalent of (Of T). E.g. GetType(GenClass(Of)).MakeGenericType(GetType(Integer)) Is GetType(GenClass(Of Integer)) returns True. So your Select Case code above becomes ' Map ValueCode to a type. Dim T As Type Select Case ValueCode Case 1 : T = GetType(String) Case 2 : T = GetType(Integer) et cetera ... End Select ' Create the generic type. Dim G As Type = GetType(GenClass(Of)).MakeGenericType(T) ' Create the object and add to the list. ObjectList.Add(Activator.CreateInstance(G)) -- Regards, Mark Hurd, B.Sc.(Ma.) (Hons.) FYI My sample code as used in Snippet Compiler with Option Infer On: (As you can see I had some trouble getting the Object() to be accepted as an argument to the List(Of) constructor.) Sub RunSnippet() WL(GetType(List(Of)).MakeGenericType(GetType(Integer)) Is GetType(List(Of Int32))) ML(GetType(Integer), 1, 2, 3) ML(GetType(String), "A", "B", "C") End Sub Sub ML(Type As Type, ParamArray Args As Object()) Dim l = GetType(List(Of)).MakeGenericType(Type) 'Dim a = GetType(IEnumerable(Of)).MakeGenericType(Type) Dim m = GetType(Enumerable).GetMethod("Cast").MakeGenericMethod(Type) Dim i = Activator.CreateInstance(l, m.Invoke(Nothing, New Object(){Args})) WL(i) For Each e In i WL(e) Next End Sub Produces this output: True System.Collections.Generic.List`1[System.Int32] 1 2 3 System.Collections.Generic.List`1[System.String] A B C
From: Captain Jack on 12 Mar 2010 13:33 "Mark Hurd" <markhurd(a)ozemail.com.au> wrote in message news:%23Ofin8ewKHA.5132(a)TK2MSFTNGP05.phx.gbl... > "Captain Jack" <CaptainJack1024(a)comcast.net> wrote in message > news:_tKdnQt1w8KPlwXWnZ2dnUVZ_vidnZ2d(a)giganews.com... >> Kinda stumped on this one... I've got a generic class, defined like this: >> >> [ ... ] > > You need to know two things: > > 1. GetType can reference generic types by including Of with out a type > name. > E.g. GetType(GenClass(Of)) > > 2. Type.MakeGenericType(T) is the runtime equivalent of (Of T). > E.g. GetType(GenClass(Of)).MakeGenericType(GetType(Integer)) Is > GetType(GenClass(Of Integer)) > returns True. That was indeed what I was looking for, thank you. I may have painted myself into a bit of a corner, though, so I'm reviewing the whole thing. The main reason I'm using a generic class in this case is so I that I can have a class that doesn't have to go through all kinds of hoops to properly compare a property found at run time in another, unrelated object to a constant pre-loaded from the database, as well as nicely enforcing the correct type in each different element of my list. That does work, no problems, and the code above makes the process of instantiating the classes much more elegant (if I switch the numeric code in the database to a string that names the type, even better). By having the generic class descend from a non-generic class, it's easire to define the list object, which was a nice plus. Each of the generic classes has a property that returns a value (the property is brilliantly named "Value") of the type defined in the generic part. Since the property "Value" is defined in the generic class, of course, when I pull an item from the list as the BaseClass, "Value" isn't recognized. I could cast the item to type Object, of course, but that shoots elegance right in the gut and leaves it for dead by the side of the road. Shadowing a dummy property in the base class doesn't seem to get me anywhere either. I'm sure there's some way around this, ultimately, but I'm beginning to think I over-complicated this one in my neverending quest for "beautiful" code. -- Jack
|
Next
|
Last
Pages: 1 2 Prev: Default Event in VB NET Next: FileSystemWatcher and syncing database with changes |