vb.net - add object to arraylist - vb.net

I'm having some trouble adding an object to an arraylist.
Basically the object has two properties (file id/name), but I can't figure out how to assign those properties. During runtime it errors out with public member on the object not found.
Private QueueList As New ArrayList
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
Dim QueueObj As New Object
QueueObj.FileID = "Test 1"
QueueObj.FileName = "Test 2"
QueueList.Add(QueueObj)
End Sub
I'd also like to know how I can do a loop on the arraylist and access the two properites on each record.
Thanks!

You can't just use "Object" for this. You need to build your own class:
Public Class File
Public Property FileID As Integer
Public Property FileName As String
Public Sub New ()
End Sub
Public Sub New(ByVal FileName As String, ByVal FileID As Integer)
Me.FileID = FileID
Me.FileName = FileName
End Sub
End Class
And then build your Queue like this:
Private QueueList As New ArrayList()
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueList.Add(New File(FileName, FileID))
End Sub
Public Sub Queue(ByVal FileObj As File)
QueueList.Add(FileObj)
End Sub
Or, even better, use generics:
Public QueueList As New List(Of File)()
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueList.Add(New File(FileName, FileID))
End Sub
Public Sub Queue(ByVal FileObj As File)
QueueList.Add(FileObj)
End Sub
Then, to loop over list:
For Each item As File In QueueList
'Console.WriteLine(item.FileID & vbTab & item.FileName)
Next item

You need to switch to an object to hold your file information, and drop ArrayList for a strongly typed collection.
public class QueueFile
public Property FileID as integer
public property FileName as string
end class
...
Private QueueList As New List(Of QueueFile)
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
Dim QueueObj As New QueueFile
QueueObj.FileID = "Test 1"
QueueObj.FileName = "Test 2"
QueueList.Add(QueueObj)
End Sub

If you only have two values, you may find using a generic Dictionary even better than an ArrayList (requiring boxing and unboxing the types) or List(Of T) which retains type safety.
Private QueueList As New Dictionary(of Integer, String)
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueList.Add(FileID, FileName)
End Sub
If you really want a Queue as your method name indicates, consider using the generic Queue. Also, if you only need a key/value pair, you don't need to create your own class. You can use the generic KeyValuePair(Of T, S):
Private QueueItems As New Queue(Of KeyValuePair(Of Integer, String))
Public Sub Queue(ByVal FileName As String, ByVal FileID As Integer)
QueueItems.Enqueue(New KeyValuePair(Of Integer, String)(FileID, FileName))
End Sub
To get items out, use the QueueItems.Dequeue.

Related

Casting substrings with linq into a list of object and than sorting it base on property in vb.net

This have to be in vb.net linq, i'm pretty sure I could do it in c#, but I cant find any good enough translator to help me ... even the answers I find here in SO seems to only be written in linq, hence the question which might be a duplicate of a c# one.
That being said, considering these 2 classes :
Public class User
Public Property Name() As String
Public Property Teams As TeamList
Public sub New(d as string, results as TeamList)
me.name = d
me.Teams = results
end sub
end class
Public Class TeamList
Public Property TeamName() As String
Public Property fullscore() As list(of object)
Public sub New(name as string, value as list(of string))
me.TeamName = name
me.fullscore = value
me.fullscore = getFullScore(value) (return a list of object)
end sub
End Class
I'm struggling in the final steps of my linq -to - object : (you can copy /paste this in linqpad)
Sub Main
dim Definition as new Dictionary(of String, object)
definition.add("user1_redTeam-02", new object)
definition.add("user1_redTeam-01", new object)
definition.add("user1_blueTeam-03", new object)
definition.add("user2_redTeam-01", new object)
definition.add("user1_redTeam-03", new object)
definition.add("user1_blueTeam-01",new object)
definition.add("user2_blueTeam-01", new object)
definition.add("user1_blueTeam-02", new object)
definition.add("user2_redTeam-02", new object)
Dim q3 = (From userlists In Definition.Keys.GroupBy(Function(s) s.Split("_")(0)) _
Select New With _
{.UserName = userlists.Key, _
.animationList = (From scList In userlists.GroupBy(Of String)(Function(s) s.Split("-")(0)) _
Select New With {.Team = scList.Key, _
.Score = scList.ToList()})})
q3.dump()
End Sub
this is the result :
now, all I want is to sort the .score attribute (just a simple .sort(), and instead of returning an anonymous q3 object, which I,m cluless to transform, I'd like the q3 to be a list(of User)
it think it should looks like this ... but I cant make it works, i always gets some linq conversion errors :
Unable to cast object of type 'WhereSelectEnumerableIterator2[System.Linq.IGrouping2[System.String,System.String],UserQuery+User]' to type 'System.Collections.Generic.List`1[UserQuery+User]'.
Dim q3 as List(of User)= (From userlists In Definition.Keys.GroupBy(Function(s) s.Split("_")(0)) _
Select New User(userlists.Key, (From scList In userlists.GroupBy(Of String)(Function(s) s.Split("-")(0)) _
Select New TeamList(scList.Key, scList.ToList()))))
Your code examples seem to be incorrect - for example, it seems like User.Teams should be a list of some type, not a TeamList object, which isn't really a list. Anyway, with a little modification, this is what I came up with - maybe it's close to what you were looking for (a list of users with the scores sorted). You can paste into LINQPad to run it.
Sub Main
Dim Definition As New Dictionary(of String, Object)
definition.add("user1_redTeam-02", New Object)
definition.add("user1_redTeam-01", New Object)
definition.add("user1_blueTeam-03", New Object)
definition.add("user2_redTeam-01", New Object)
definition.add("user1_redTeam-03", New Object)
definition.add("user1_blueTeam-01",New Object)
definition.add("user2_blueTeam-01", New Object)
definition.add("user1_blueTeam-02", New Object)
definition.add("user2_redTeam-02", New Object)
Dim q3 = (
From userlists In Definition.Keys.GroupBy(Function(s) s.Split("_"c)(0))
Select New User(
userlists.Key,
(From scList In userlists.GroupBy(Function(s) s.Split("-"c)(0))
Select New Team(scList.Key.Split("_"c)(1), scList.OrderBy(Function(s) s).ToList())).ToList()
)
).ToList()
q3.dump()
End Sub
' Define other methods and classes here
Public class User
Public Property Name() As String
Public Property Teams() As List(Of Team)
Public Sub New(d As String, results As List(Of Team))
Me.Name = d
Me.Teams = results
End Sub
End Class
Public Class Team
Public Property TeamName() As String
Public Property FullScore() As List(Of String)
Public Sub New(name As String, value As List(Of String))
Me.TeamName = name
Me.FullScore = value
End Sub
End Class

Sharing a List of(String) between Private Sub

In my code I basically read a textbox and put each line into a list (Of String) Dim "testblock" in code below
From there I create another list (of string) and split each line whenever a space is found. Dim "block" in code below
Now I want to be able to access that list from anywhere in the project.
How do I go about sharing a List of(String) between Private Sub such as form buttons?
Private Sub PhaseCodeBTN_Click(sender As Object, e As EventArgs) Handles PhaseCodeBTN.Click
Dim testblock As New List(Of String)
Dim lines As String() = TextBox1.Text.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
Dim block As New List(Of String)
For Each l As String In lines
testblock.Add(l)
Dim words As String() = BlockCodeBox.Text.Split(" ")
For Each splitword As String In words
block.Add(splitword)
Next
Next
BlockCodeBox.Text = testblock(BlockNumBox.Text)
WordCmdBox.Text = block(WordNumBox.Text)
End Sub
Private Sub PhaseBlackBTN_Click(sender As Object, e As EventArgs) Handles PhaseBlackBTN.Click
WordCmdBox.Text = block(WordNumBox.Text)
End Sub
Create a Public Shared Class with your List(Of String) there to use it anywhere in the project:
Public Shared Class DataHolder
Private _block As New List(Of String)
Public Property Block As List(Of String)
Get
Return _block
End Get
Set
_block = value
End Set
End Property
End Class
Example:
Either simply use DataHolder.Block.Add(splitword) OR following steps:
Declare a class variable block to use it in entire class:
Private block As List(Of String)
Initialize it in some suitable function / event-handler like Form_Load:
block = DataHolder.Block
Do the operation:
block.Add(splitword)

Duplicate Settings In Reference DLL

I have a DLL with several properties and a function that generates runs a SSRS report in the background and saves it to a PDF file.
I have a DataTable with all the reports that need to be generated and where they need to be saved.
I want to make each instance of the DLL run in a separate thread. I took a stab at it found the 2nd row in the DataTable overrode the first row.
Here is the Class/DLL Code
Public Class SSRSFunctions
Private Shared _Formated_Parameters As String
Private Shared _Report_Parameters As Dictionary(Of String, String)
Public Property FORMATED_PARAMETERS() As String
Get
Return _Formated_Parameters
End Get
Set(ByVal value As String)
_Formated_Parameters = value
End Set
End Property
Public Sub New()
_Report_Parameters = New Dictionary(Of String, String)
End Sub
Public Function RenderReportToFile() As String
'RenderReportHere
End Function
Public Sub AddParameter(ByVal Name As String, ByVal Value As String)
If _Report_Parameters.ContainsKey(Name) Then
_Report_Parameters.Remove(Name)
_Report_Parameters.Add(Name, Value)
Else
_Report_Parameters.Add(Name, Value)
End If
End Sub
End Class
Here is the calling Code
Private Sub CheckForNewRequests()
'Filter DataTable for Reports to Run
For Each dr As DataRow in DateTable.Rows
Dim rpt As New SSRSFunctions
Dim t1 As New Threading.Thread(AddressOf StartNewThread)
rpt.FORMATED_PARAMETERS = (dr("REPORT_PARAMS"))
t1.Start(rpt)
Next
End Sub
Private Function StartNewThread(ByVal report As SSRSFunctions) As String
Return report.RenderReportToFile()
End Function
I am trying to figure out why the "Dim rpt As New SSRSFunctions" is not creating a new instance of the DLL and so the second row of the dataTable has a new instance to store it's parameters.
The second row is overriding the first.
Help?
Thanks
jlimited
Dont make the private properties shared, remove the Shared keyword from the declarations.
change
Private Shared _Formated_Parameters As String
Private Shared _Report_Parameters As Dictionary(Of String, String)
to
Private _Formated_Parameters As String
Private _Report_Parameters As Dictionary(Of String, String)
By sharing them you are saying that no matter how many instances of the class is created always use (share) the same instance of the shared internal variable.

Do local variables in shared method work like static variable in C?

Will the list in this shared method keep its state throughout the life of the method? Or will a new list be created every time this method is called?
Protected Shared Function newResxNodes(ByVal newName As String, ByVal newValue As String, Optional ByVal newComment As String = "") As List(Of ResXDataNode)
Dim newResxNodesList As List(Of ResXDataNode) = New List(Of ResXDataNode)
Dim newResxNode As ResXDataNode = New ResXDataNode(newName, newValue)
If newComment <> String.Empty Then
newResxNode.Comment = newComment
End If
newResxNodesList.Add(newResxNode)
Return newResxNodesList
End Function
No, It does not work like static variables in C. It will be a new list for every call. If you want to retain the list and list items, create a shared class field.
I've done a test and it returns 3 lines.
Module Module1
Class b
Public Sub New()
Console.WriteLine("New")
End Sub
End Class
Class a
Public Shared Sub Test()
Dim c As b = New b
End Sub
End Class
Sub Main()
a.Test()
a.Test()
a.Test()
Console.ReadLine()
End Sub
End Module

Is it possible to make a shared function generic?

I can create classes that use generics, however I was wondering if it is possible to apply this to a shared method rather than rely on the caller casting to the correct type.
This is the method:
Public Shared Function DeserializeObject(ByVal serializedXml As String, ByVal givenType As System.Type) As Object
Dim serializer As New XmlSerializer(givenType)
Return serializer.Deserialize(New IO.StringReader(serializedXml))
End Function
I'm pretty sure this can't be done, but thought I'd check (if so Extra points will be awarded if someone can technically explain why the compiler can't do this).. Alternative suggestions would also be appreciated.
Public Shared Function StronglyTypedDeserializeObject(Of T)
(ByVal serializedXml As String) As T
Dim serializer As New XmlSerializer(GetType(T))
Return DirectCast(
serializer.Deserialize(New IO.StringReader(serializedXml))
, T)
End Function
Note that invocations will have to supply the type expected:
Dim foo As MyType
= Utility.StronglyTypedDeserializeObject(Of MyType)(sourceXml)
There's no reason you couldn't create a generic version of the function. e.g.:
Public Shared Function Deserialize(Of T)(ByVal serializedXml As String) As T
Dim serializer As New XmlSerializer(GetType(T))
Return DirectCast(serializer.Deserialize(New StringReader(serializedXml)), T)
End Function
The Following Example shows how you can do this. The esstential trick is remember that can you can use the GetType function a defined Generic for example GetType(MyObject(Of T))
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Test1 As New MyObject(Of String)
Dim Test2 As New MyObject(Of Integer)
Dim Data As String = ""
Test1.Data = "Hello World"
Test2.Data = 1010101
Data = Test1.SerializeObject
Test1 = MyObject(Of String).DeserializeObject(Data)
Debug.Print(Test1.Data)
Data = Test2.SerializeObject
Test2 = MyObject(Of Integer).DeserializeObject(Data)
Debug.Print(Test2.Data)
End Sub
End Class
Public Class MyObject(Of T)
Public Data As T
Public Sub New()
End Sub
Public Shared Function DeserializeObject(ByVal serializedXml As String) As MyObject(Of T)
Dim serializer As New XmlSerializer(GetType(MyObject(Of T)))
Return serializer.Deserialize(New IO.StringReader(serializedXml))
End Function
Public Function SerializeObject() As String
Dim serializer As New XmlSerializer(GetType(MyObject(Of T)))
Dim Result As New IO.StringWriter()
serializer.Serialize(Result, Me)
Return Result.ToString
End Function
End Class
If you don't like fully qualifying the type to get at the shared member then you can do something like this.
Public Class MyObjectString
Inherits MyObject(Of String)
End Class
Then you can call MyObjectString.Deserialize