List Of - Insert only if GUID doesn't exist - vb.net

Before I add an item to my List (Of clsUser), I check if no clsUser with the same GUID exists in my list.
Currently I check for the existance like this:
Public Function GUIDExists(ByRef uList As List (Of clsUser), ByVal uGUID As String) As Boolean
For Each nItem As clsUser In uList
If nItem.GUID = uGUID Then
Return True
End If
Next
Return False
End Function
I would very much like simplify it and add this check to the List (Of clsUser) so that I don't have to write the same code over and over again.
Some like MyList.AddIfGUIDDoesntExists(nNewUser)
Is this possible?
If yes, could anybody tell me how this would be done?

Imports System.Runtime.CompilerServices
Public Module ExtensionMethods
<Extension()>
Public Sub AddIfGUIDDoesntExists(ByRef inputList As List(Of clsUser), _
ByVal item As clsUser)
Dim contains As Boolean = False
For Each i As clsUser In inputList
If (i.GUID = item.GUID) Then
contains = True
Exit For
End If
Next
If Not contains
inputList.Add(item)
End If
End Sub
End Module
Usage:
MyList.AddIfGUIDDoesntExists(nNewUser)

Related

Get elements with certain condition from List(Of)

I'm iterating through a List(Of MyClass) in order to find elements with certain conditions.
For example, in one case, I need to find all of these elements and do something with them:
For Each nCell As clsCell In colCell
If nCell.TempClickIndex = nCell.ClickIndex Then
If nCell.StandardCellType = eStandardCellType.SCT_SKYPEMESSAGE Then
I would like to know if there's any way to simplify this.
I'm dreaming of something like this:
For Each nCell As clsCell in colCell.GetSkypeCells()
The call "GetSkypeCells" would do just what I do above and would handle the selection internally.
Is there a way to do this?
Edit:
This is my colCell:
Public colCell As New clsCellListExtender.List(Of clsCell)
Imports System.Collections.ObjectModel
Public Class clsCellListExtender
Public Class List(Of T)
Inherits Collection(Of T)
Private _iID As Integer = 0
Private i As Integer = 0
Protected Overrides Sub InsertItem(index As Integer, item As T)
'your checks here
'i += 1
'If i > 20000 Then
' i = 0
'End If
Debug.Assert(g_bCheck = False)
If TypeOf (item) Is clsCell Then
_iID += 1
Dim nCell As clsCell = TryCast(item, clsCell)
nCell.TempID = _iID
End If
MyBase.InsertItem(index, item)
End Sub
End Class
End Class
You could use this:
For Each nCell as clsCell In colCell.Where(Function(x) x.TempClickIndex = x.ClickIndex AndAlso x.StandardCellType = eStandardCellType.SCT_SKYPEMESSAGE)
'Do stuff with nCell
Next
For your "dream" solution, you could add an extension method to whatever type colCell is that returns the result of the above LINQ.
Getting this to work with the nested class, and the generic type was a little tricky, but I finally got it.
Public Module Extensions
<System.Runtime.CompilerServices.Extension()> _
Public Function GetSkypeCells(Of T As clsCell)(colCell As clsCellListExtender.List(Of T)) As IEnumerable(Of T)
Return colCell.Where(Function(x) x.TempClickIndex = x.ClickIndex AndAlso x.StandardCellType = eStandardCellType.SCT_SKYPEMESSAGE)
End Function
End Module
Here is a small console application with a working extension method. I left the implementation blank to save space, but you should be able to fill it in from what is above. Just let me know if you have any issues.
Imports System.Collections.ObjectModel
Imports System.Runtime.CompilerServices
Module Module1
Sub Main()
Dim a As New clsCellListExtender.List(Of clsCell)
For Each cell As clsCell In a.GetSkypeCells()
'Do things with cell here
Next
End Sub
End Module
Public Class clsCellListExtender
Public Class List(Of T)
Inherits Collection(Of T)
Protected Overrides Sub InsertItem(index As Integer, item As T)
'...
End Sub
End Class
End Class
Public Class clsCell
'...
End Class
Module Extensions
<Extension>
Public Function GetSkypeCells(Of T As clsCell)(colCell As clsCellListExtender.List(Of T)) As IEnumerable(Of T)
Return colCell.Where(Function(x) x.TempClickIndex = x.ClickIndex AndAlso x.StandardCellType = eStandardCellType.SCT_SKYPEMESSAGE)
End Function
End Module
Try this:
For Each nCell As clsCell In colCell.FindAll(Function(c) c.TempClickIndex = c.ClickIndex And
c.StandardCellType = eStandardCellType.SCT_SKYPEMESSAGE)
Next
You can adapt this and create an extension-method, then you can call it with colCell.GetSkypeCells()
<Extension>
Public Function GetSkypeCells(c As List(Of clsCell)) As List(Of clsCell)
Return c.FindAll(Function(cc As clsCell) cc.TempClickIndex = cc.ClickIndex And
cc.StandardCellType = eStandardCellType.SCT_SKYPEMESSAGE)
End Function
You can use LINQ's extension method Where
Dim skypeCalls =
colCell.Where(Function(cell) cell.TempClickIndex = cell.ClickIndex).
.Where(Function(cell) cell.StandardCellType = eStandardCellType.SCT_SKYPEMESSAG)
For Each skypeCall in skypeCalls
' Do something
Next

Collection class of specific type containing basic features

Every time i use some class e.g Artikel as follows:
Public Class Artikel
Property ID As Integer
Property Nummer As String
Property Name As String
Property Position As Integer
End Class
For such classes i would like to have collection class. The features i would like to have is like:
--> Add (passing Artikel object)
--> Remove (passing Artikel object)
--> Sort entire collection (based on Position property desc/asc)
--> Compare two Artikels (pass by Artikels and tell by which property has to be compared)
--> Check whether two artikels equals
--> Every added artikel has to be marked by Key (so maybe dictionary)? <key><Artikel>
--> Remove Artikel (passing by Key index)
Could somone from you there tell me or even better provide example of collection class pass those requirments?
EDIT: Startup:
Artikel's collection:
Option Strict On
Public Class Articles
Public Property collection As Dictionary(Of Integer, Artikel)
Sub New()
'Initiate new collection
collection = New Dictionary(Of Integer, Artikel)
End Sub
'Add new Artikel to collection
Public Function AddToCollection(ByVal artikel As Artikel) As Boolean
collection.Add(artikel)
Return True
End Function
'Remove specific Artikel
Public Sub RemoveFromCollectionByArtikel(artikel As Artikel)
If Not IsNothing(collection) Then
collection.Remove(artikel)
End If
End Sub
'Get collection
Public Function GetCollection() As Dictionary(Of Integer, Artikel)
Return collection
End Function
'Sort collection by property position
Public Sub SortByPosition()
collection.Sort()
End Sub
'Remove specific sending keys and then reorder them
Public Sub RemoveAllMarkedAsDeleted(keys As List(Of Integer))
'-- Check whther anything has been marked as deleted
If keys.Count > 0 Then
For Each row In keys
collection.Remove(row)
Next
ReorderKeys()
End If
'Reorder all Artikels in collection
Private Sub ReorderKeys()
Dim newCollection As New Dictionary(Of Integer, Artikel)
Dim index As Integer = 0
For Each collitem In collection
newCollection.Add(index, collitem.Value)
index += 1
Next
collection.Clear()
collection = newCollection
End Sub
End Class
Artikel class (additionally i implemented IComparable to be able to sort)
Option Strict On
Public Class Artikel
Implements IComparable(Of Artikel)
Property ID As Integer
Property Nummer As String
Property Name As String
Property Position As Integer
Public Function CompareTo(pother As Artikel) As Integer Implements IComparable(Of Artikel).CompareTo 'we can sort because of this
Return String.Compare(Me.Position, pother.Position)
End Function
Public Shared Function FindPredicate(ByVal partikel As Artikel) As Predicate(Of Artikel)
Return Function(partikel2 As Artikel) partikel.ID = partikel2.ID
End Function
Public Shared Function FindPredicateByUserId(ByVal partikel As String) As Predicate(Of Artikel)
Return Function(partikel2 As Artikel) partikel = partikel2.ID
End Function
End Class
Parts of it look good, but I would ultimately do it a bit differently. First, consider overloads on the item class to make them easier to create and default initialization:
Public Class Article
Property ID As Integer = -1
Property Key As String = ""
Property Name As String = ""
Property Position As Integer = -1
Property PubDate As DateTime = DateTime.Minimum
Public Sub New()
End Sub
' whatever minimum data a new item requires
Public Sub New(k As String, n As String)
Key = k
Name = n
End Sub
' full initialization:
Public Sub New(k As String, n As String, pos As Int32,
pubDt As DateTime)
...
End Sub
End Class
I added some properties for variety, and I suspect "Nummer" might be the "Key" mentioned in the OP, but whatever it is, I would add it to the Article class as that name, if it has some importance.
You might need a simple ctor for serialization (???). Some of these will find and use a Private parameterless constructor, but your code will be forced to use one of the overloads in order to provide some minimum level of data when a new one is created.
You probably do not need IComparable. That is typically for more complex comparisons, such as multiple or complex properties. An example is a carton or box:
If (width = Other.Width) AndAlso (height = Other.Height) Then
Return 0
ElseIf (width = Other.Height) AndAlso (height = Other.Width) Then
Return 0
End If
Plus more gyrations to work out which is "less" than the other. One reason you dont need it, is because If Art1.Postion > Art2.Postion is trivial. The other reason in your case, is because a Dictionary cannot be sorted.
Rather than a Dictionary, an internal List would work better for some of the things you describe but still allow you to have it act like a Dictionary to the extent you need it to. For this, I might build it using ICollection<T>:
Public Class ArticleCollection
Implements ICollection(Of Article)
Pressing Enter after that line will add all the required methods including:
Public Sub Add(item As Article) Implements ICollection(Of Article).Add
Public Sub Clear() Implements ICollection(Of Article).Clear
Public Function Contains(item As Article) As Boolean Implements ICollection(Of Article).Contains
Public ReadOnly Property Count As Integer Implements ICollection(Of Article).Count
Public Function Remove(item As Article) As Boolean Implements ICollection(Of Article).Remove
It remains completely up to you how these are implemented. It also doesn't rule out adding methods such as RemoveAt(int32) or RemoveByKey(string) depending on what you need/how it will be used. One of the benefits to ICollection(Of T) is that it includes IEnumerable which will allow use for each loops (once you write the Enumerator): For Each art In Articles
To emulate a dictionary to allow only one item with a specific property value:
Public Class ArticleCollection
Implements ICollection(Of Article)
Private mcol As List(Of Article)
...
Public Sub Add(item As Article) Implements ICollection(Of Article).Add
' check for existing key
If KeyExists(item.Key) = False Then
mcol.Add(item)
End If
End Sub
You can also overload them:
' overload to match Article ctor overload
Public Sub Add(key As String, name As String)
If KeyExists(key) = False Then
' let collection create the new item
' with the minimum required info
mcol.Add(New Article(key, name))
End If
End Sub
If you add an Item Property, you can index the collection ( Articles(3) ):
Property Item(ndx As Int32) As Article
Get
If ndx > 0 AndAlso ndx < mcol.Count Then
Return mcol(ndx)
Else
Return Nothing
End If
End Get
Set(value As Article)
If ndx > 0 AndAlso ndx < mcol.Count Then
mcol(ndx) = value
End If
End Set
End Property
' overload for item by key:
Public Property Item(key As String) As Article
An Add method and an Item Property will be important if the collection will display in the standard NET CollectionEditor.
There are several ways to implement sorting. The easiest is to use linq in the code which uses your collection:
Articles = New ArticleCollection
' add Article items
Dim ArticlesByDate = Articles.OrderBy(Function(s) s.PubDate).ToList()
Where PubDate is one of the Article properties I added. The other way to handle sorting is by the collection class returning a new collection (but it is so simple to do, there is little need for it):
Friend Function GetSortedList(bSortAsc As Boolean) As List(Of Article)
If bSortAsc Then
Return mcol.OrderBy(Function(q) q.PubDate).
ThenBy(Function(j) j.Position).ToList()
Else
Return mcol.OrderByDescending(Function(q) q.PubDate).
ThenByDescending(Function(j) j.Position).ToList()
End If
End Function
Whether it implements ICollection(Of T), inherits from ICollection(Of T) or does work off a Dictionary depends entirely on what this is, how it is used and whatever rules and restrictions there are (including if it will be serialized and how). These are not things we know.
MSDN has an article on Guidelines for Collections which is excellent.
Create your class
Public Class Artikel
Property ID As Integer
Property Nummer As String
Property Name As String
Property Position As Integer
sub new (_ID as integer, _Nummer as string, _Name as string, _Position as integer)
ID = _ID
Nummer = _Nummer
Name = _Name
Position = _Position
End Sub
End Class
Create another class which holds a private list and add sub routines to it
Public Class ArtikelList
Private _List as new list (of Artikel)
Public sub remove(Key as integer)
Dim obj as Artikel = nothing
for each x as Artikel in _List
if x.ID = Key then
obj = x
exit for
end if
Next
if not isnothing(obj) then
_List.remove(obj)
end if
End sub
Sub Add(obj as Artikel)
Dim alreadyDeclared as boolean = falsse
for each x as Artikel in _List
if x.ID = obj.id then
alreadyDeclared = true
exit for
end if
Next
if not AlreadyDeclared then
_List.add(obj)
Else
'Somehow inform the user of the duplication if need be.
end if
End sub
End Class
Then use your list class.
dim L as new ArtikelList
L.add(new Artikel(1280, "AFKforever!", "Prof.FluffyButton", 96))
L.remove(1280)
I only added one sub routine as an example. I hope it helps but feel free to ask for more example routines.
This can also be done by creating a class which inherits from the list class, exposing all list class functionality but by using this method you are forced to create every subroutine that will be used. This way you only use routines that you created exclusively for the purpose Artikel objects handling.
Check if two Artikels are equal
Public Class Artikel
Property ID As Integer
Property Nummer As String
Property Name As String
Property Position As Integer
sub new (_ID as integer, _Nummer as string, _Name as string, _Position as integer)
ID = _ID
Nummer = _Nummer
Name = _Name
Position = _Position
End Sub
End Class
Public Overrides Overloads Function Equals(obj As Object) As Boolean
If obj Is Nothing OrElse Not Me.GetType() Is obj.GetType() Then
Return False
else
dim _obj as artikel = obj
if Me.ID = _obj.ID then
Return true
else Return False
End If
End Function
End Class
Use it like:
If x.equals(y) then
'they have the same ID
end if

Read Text File Line by Line and Take Input from what ever proceeds '=' [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
newbie question but I can't seem to find a definitive way to do this. I want the program to be able to take information from particular lines of text files and use that information for a variety of tasks. I'd really appreciate it if you could also teach me how to write to a particular line of the text file.
Here's an example of the text file:
Line1 Name = Garry
Line2 Set = 0
Line3 Other = Other
Plus many more lines
The tricky part is to grab the information that comes after the '=' on line 2 for example. And also if the user wanted to change one of the information on these lines, how I'd go around changing it... I would appreciate any help what so ever.
*Using Visual Basic Studio 2012 on .net 4.5
And if you want to do it simply:
First read all lines of the file
Dim Lines() as String = IO.File.ReadAllLines("C:\myfile.txt")
The array then contains elements for each line in the file.
Then iterate through these lines:
Dim MyKeyValues As New Dictionary(Of String, String) 'See below
For each line as String in Lines
Dim LineParts() as String = Strings.Split(line, "=", 2) 'Split the current line into two chunks at the first =
If LineParts.Count < 2 Then
Continue For 'No = in the line, so skip it
Else
Dim Key as String = LineParts(0)
Dim Value as String = LineParts(1) 'This contains the part after the =
'Do whatever you want with the value here. e.g.
MyKeyValues.Add(Key, Value) 'See below
Endif
Next
You can for example save the line parts into a Dictionary(Of String, String) and make the changes to the values in this dictionary. Afterwards write the dictionary back to the file:
Dim FileLines as New List(Of String)
For each k as String in MyKeyValues.Keys
FileLines.Add(k & "=" & MyKeyValues(k))
Next
IO.File.WriteAllLines("C:\myfile.txt", FileLines)
The ReadAllLines() and WriteAllLines() methods should be reasonably fast if the textfile is not extremely large. As others have pointed out an INIFile class should be most suitable for your needs since this makes it easy to read and change keys.
This is very similar to an INI file except without headers.
Here is an example of an INI file:
[CONFIG] Header
Option1=true Key=Value
Option2=true Key=Value
Option3=false Key=Value
You can read and write to INI files easily by using this class in your project:
Imports System.IO
Imports System.Text.RegularExpressions
Imports System.Collections
Imports System.Diagnostics
Public Class IniFile
' List of IniSection objects keeps track of all the sections in the INI file
Private m_sections As Hashtable
' Public constructor
Public Sub New()
m_sections = New Hashtable(StringComparer.InvariantCultureIgnoreCase)
End Sub
' Loads the Reads the data in the ini file into the IniFile object
Public Sub Load(ByVal sFileName As String, Optional ByVal bMerge As Boolean = False)
If Not bMerge Then
RemoveAllSections()
End If
' Clear the object...
Dim tempsection As IniSection = Nothing
Dim oReader As New StreamReader(sFileName)
Dim regexcomment As New Regex("^([\s]*#.*)", (RegexOptions.Singleline Or RegexOptions.IgnoreCase))
' Broken but left for history
'Dim regexsection As New Regex("\[[\s]*([^\[\s].*[^\s\]])[\s]*\]", (RegexOptions.Singleline Or RegexOptions.IgnoreCase))
Dim regexsection As New Regex("^[\s]*\[[\s]*([^\[\s].*[^\s\]])[\s]*\][\s]*$", (RegexOptions.Singleline Or RegexOptions.IgnoreCase))
Dim regexkey As New Regex("^\s*([^=\s]*)[^=]*=(.*)", (RegexOptions.Singleline Or RegexOptions.IgnoreCase))
While Not oReader.EndOfStream
Dim line As String = oReader.ReadLine()
If line <> String.Empty Then
Dim m As Match = Nothing
If regexcomment.Match(line).Success Then
m = regexcomment.Match(line)
Trace.WriteLine(String.Format("Skipping Comment: {0}", m.Groups(0).Value))
ElseIf regexsection.Match(line).Success Then
m = regexsection.Match(line)
Trace.WriteLine(String.Format("Adding section [{0}]", m.Groups(1).Value))
tempsection = AddSection(m.Groups(1).Value)
ElseIf regexkey.Match(line).Success AndAlso tempsection IsNot Nothing Then
m = regexkey.Match(line)
Trace.WriteLine(String.Format("Adding Key [{0}]=[{1}]", m.Groups(1).Value, m.Groups(2).Value))
tempsection.AddKey(m.Groups(1).Value).Value = m.Groups(2).Value
ElseIf tempsection IsNot Nothing Then
' Handle Key without value
Trace.WriteLine(String.Format("Adding Key [{0}]", line))
tempsection.AddKey(line)
Else
' This should not occur unless the tempsection is not created yet...
Trace.WriteLine(String.Format("Skipping unknown type of data: {0}", line))
End If
End If
End While
oReader.Close()
End Sub
' Used to save the data back to the file or your choice
Public Sub Save(ByVal sFileName As String)
Dim oWriter As New StreamWriter(sFileName, False)
For Each s As IniSection In Sections
Trace.WriteLine(String.Format("Writing Section: [{0}]", s.Name))
oWriter.WriteLine(String.Format("[{0}]", s.Name))
For Each k As IniSection.IniKey In s.Keys
If k.Value <> String.Empty Then
Trace.WriteLine(String.Format("Writing Key: {0}={1}", k.Name, k.Value))
oWriter.WriteLine(String.Format("{0}={1}", k.Name, k.Value))
Else
Trace.WriteLine(String.Format("Writing Key: {0}", k.Name))
oWriter.WriteLine(String.Format("{0}", k.Name))
End If
Next
Next
oWriter.Close()
End Sub
' Gets all the sections
Public ReadOnly Property Sections() As System.Collections.ICollection
Get
Return m_sections.Values
End Get
End Property
' Adds a section to the IniFile object, returns a IniSection object to the new or existing object
Public Function AddSection(ByVal sSection As String) As IniSection
Dim s As IniSection = Nothing
sSection = sSection.Trim()
' Trim spaces
If m_sections.ContainsKey(sSection) Then
s = DirectCast(m_sections(sSection), IniSection)
Else
s = New IniSection(Me, sSection)
m_sections(sSection) = s
End If
Return s
End Function
' Removes a section by its name sSection, returns trus on success
Public Function RemoveSection(ByVal sSection As String) As Boolean
sSection = sSection.Trim()
Return RemoveSection(GetSection(sSection))
End Function
' Removes section by object, returns trus on success
Public Function RemoveSection(ByVal Section As IniSection) As Boolean
If Section IsNot Nothing Then
Try
m_sections.Remove(Section.Name)
Return True
Catch ex As Exception
Trace.WriteLine(ex.Message)
End Try
End If
Return False
End Function
' Removes all existing sections, returns trus on success
Public Function RemoveAllSections() As Boolean
m_sections.Clear()
Return (m_sections.Count = 0)
End Function
' Returns an IniSection to the section by name, NULL if it was not found
Public Function GetSection(ByVal sSection As String) As IniSection
sSection = sSection.Trim()
' Trim spaces
If m_sections.ContainsKey(sSection) Then
Return DirectCast(m_sections(sSection), IniSection)
End If
Return Nothing
End Function
' Returns a KeyValue in a certain section
Public Function GetKeyValue(ByVal sSection As String, ByVal sKey As String) As String
Dim s As IniSection = GetSection(sSection)
If s IsNot Nothing Then
Dim k As IniSection.IniKey = s.GetKey(sKey)
If k IsNot Nothing Then
Return k.Value
End If
End If
Return String.Empty
End Function
' Sets a KeyValuePair in a certain section
Public Function SetKeyValue(ByVal sSection As String, ByVal sKey As String, ByVal sValue As String) As Boolean
Dim s As IniSection = AddSection(sSection)
If s IsNot Nothing Then
Dim k As IniSection.IniKey = s.AddKey(sKey)
If k IsNot Nothing Then
k.Value = sValue
Return True
End If
End If
Return False
End Function
' Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSection
Public Function RenameSection(ByVal sSection As String, ByVal sNewSection As String) As Boolean
' Note string trims are done in lower calls.
Dim bRval As Boolean = False
Dim s As IniSection = GetSection(sSection)
If s IsNot Nothing Then
bRval = s.SetName(sNewSection)
End If
Return bRval
End Function
' Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewKey
Public Function RenameKey(ByVal sSection As String, ByVal sKey As String, ByVal sNewKey As String) As Boolean
' Note string trims are done in lower calls.
Dim s As IniSection = GetSection(sSection)
If s IsNot Nothing Then
Dim k As IniSection.IniKey = s.GetKey(sKey)
If k IsNot Nothing Then
Return k.SetName(sNewKey)
End If
End If
Return False
End Function
' Remove a key by section name and key name
Public Function RemoveKey(ByVal sSection As String, ByVal sKey As String) As Boolean
Dim s As IniSection = GetSection(sSection)
If s IsNot Nothing Then
Return s.RemoveKey(sKey)
End If
Return False
End Function
' IniSection class
Public Class IniSection
' IniFile IniFile object instance
Private m_pIniFile As IniFile
' Name of the section
Private m_sSection As String
' List of IniKeys in the section
Private m_keys As Hashtable
' Constuctor so objects are internally managed
Protected Friend Sub New(ByVal parent As IniFile, ByVal sSection As String)
m_pIniFile = parent
m_sSection = sSection
m_keys = New Hashtable(StringComparer.InvariantCultureIgnoreCase)
End Sub
' Returns all the keys in a section
Public ReadOnly Property Keys() As System.Collections.ICollection
Get
Return m_keys.Values
End Get
End Property
' Returns the section name
Public ReadOnly Property Name() As String
Get
Return m_sSection
End Get
End Property
' Adds a key to the IniSection object, returns a IniKey object to the new or existing object
Public Function AddKey(ByVal sKey As String) As IniKey
sKey = sKey.Trim()
Dim k As IniSection.IniKey = Nothing
If sKey.Length <> 0 Then
If m_keys.ContainsKey(sKey) Then
k = DirectCast(m_keys(sKey), IniKey)
Else
k = New IniSection.IniKey(Me, sKey)
m_keys(sKey) = k
End If
End If
Return k
End Function
' Removes a single key by string
Public Function RemoveKey(ByVal sKey As String) As Boolean
Return RemoveKey(GetKey(sKey))
End Function
' Removes a single key by IniKey object
Public Function RemoveKey(ByVal Key As IniKey) As Boolean
If Key IsNot Nothing Then
Try
m_keys.Remove(Key.Name)
Return True
Catch ex As Exception
Trace.WriteLine(ex.Message)
End Try
End If
Return False
End Function
' Removes all the keys in the section
Public Function RemoveAllKeys() As Boolean
m_keys.Clear()
Return (m_keys.Count = 0)
End Function
' Returns a IniKey object to the key by name, NULL if it was not found
Public Function GetKey(ByVal sKey As String) As IniKey
sKey = sKey.Trim()
If m_keys.ContainsKey(sKey) Then
Return DirectCast(m_keys(sKey), IniKey)
End If
Return Nothing
End Function
' Sets the section name, returns true on success, fails if the section
' name sSection already exists
Public Function SetName(ByVal sSection As String) As Boolean
sSection = sSection.Trim()
If sSection.Length <> 0 Then
' Get existing section if it even exists...
Dim s As IniSection = m_pIniFile.GetSection(sSection)
If s IsNot Me AndAlso s IsNot Nothing Then
Return False
End If
Try
' Remove the current section
m_pIniFile.m_sections.Remove(m_sSection)
' Set the new section name to this object
m_pIniFile.m_sections(sSection) = Me
' Set the new section name
m_sSection = sSection
Return True
Catch ex As Exception
Trace.WriteLine(ex.Message)
End Try
End If
Return False
End Function
' Returns the section name
Public Function GetName() As String
Return m_sSection
End Function
' IniKey class
Public Class IniKey
' Name of the Key
Private m_sKey As String
' Value associated
Private m_sValue As String
' Pointer to the parent CIniSection
Private m_section As IniSection
' Constuctor so objects are internally managed
Protected Friend Sub New(ByVal parent As IniSection, ByVal sKey As String)
m_section = parent
m_sKey = sKey
End Sub
' Returns the name of the Key
Public ReadOnly Property Name() As String
Get
Return m_sKey
End Get
End Property
' Sets or Gets the value of the key
Public Property Value() As String
Get
Return m_sValue
End Get
Set(ByVal value As String)
m_sValue = value
End Set
End Property
' Sets the value of the key
Public Sub SetValue(ByVal sValue As String)
m_sValue = sValue
End Sub
' Returns the value of the Key
Public Function GetValue() As String
Return m_sValue
End Function
' Sets the key name
' Returns true on success, fails if the section name sKey already exists
Public Function SetName(ByVal sKey As String) As Boolean
sKey = sKey.Trim()
If sKey.Length <> 0 Then
Dim k As IniKey = m_section.GetKey(sKey)
If k IsNot Me AndAlso k IsNot Nothing Then
Return False
End If
Try
' Remove the current key
m_section.m_keys.Remove(m_sKey)
' Set the new key name to this object
m_section.m_keys(sKey) = Me
' Set the new key name
m_sKey = sKey
Return True
Catch ex As Exception
Trace.WriteLine(ex.Message)
End Try
End If
Return False
End Function
' Returns the name of the Key
Public Function GetName() As String
Return m_sKey
End Function
End Class
' End of IniKey class
End Class
' End of IniSection class
End Class
Here is an example of how to use this class:
Private Sub WriteValuesToIniFile()
Dim IniFileConfig As New IniFile
IniFileConfig.Load("C:\User\SumGuy\Desktop\Config.ini")
IniFileConfig.SetKeyValue("CONFIG", "Key1", "Value")
IniFileConfig.Save("C:\User\SumGuy\Desktop\Config.ini")
End Sub
This will write this to an ini file:
[CONFIG]
Key1=Value

Populating a combo box with a list of functions - Need Advice

I'm looking for some advice on the best way to handle this.
I have a list of about 200 "Functions" which are listed in a combo box. When the user selects a 'function' from the list, I need to return the functionID (integer).
I know this can be done easily by binding a dataset to the key and value of the combobox, I'm just not sure about the best way to populate the dataset.
I feel that the way I'm doing it currently is very convoluted:
I currently have a txt file as an embedded resource which I write to a temporary directory, then I use the following code to read in that text file and populate that box by setting the combobox's datasource and Display Member. It does this by way of a custom class which is implementing System.Collections.IList.
I have pasted the code below. The reason I want to simplify it is that I dislike writing the text file to the disk, because sometimes it fails.
I'm looking for a way to populate my combobox and return my ID, without writing anything to the user's temp folder.
I am open to changing the format of the embedded resource, and or the code.
The fnlist.txt is formatted currently as follows.
index, Function Name, ID
The index is only included for sorting (to keep NONE at the bottom, and unknown function at the top), and I suppose is not strictly required.
#Region "Function lookup"
Dim path As String = System.IO.Path.GetTempPath
Dim _objFnXtef As New clsFunctionXref(path & "fnList.txt")
Private Sub populate_list()
functionlist.DataSource = _objFnXtef
functionlist.DisplayMember = "StrFunction"
End Sub 'Populates the function list
Function get_index(ByVal fnid As Integer)
Dim iLookupNumber As Integer = fnid
Dim tmpFnInfo As New clsFunctionInfo
Dim iReturnIdx As Integer = -1
If iLookupNumber <> 0 Then
tmpFnInfo.IFunctionNumber = iLookupNumber
iReturnIdx = _objFnXtef.IndexOf(tmpFnInfo)
If iReturnIdx <> -1 Then
Return iReturnIdx - 1
Else
Return get_index(9999)
End If
End If
Return 0
End Function 'Returns index of specified function number
#End Region 'All function list functions
Here is the code when a user changes the drop down:
Private Sub functionlist_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles functionlist.SelectedIndexChanged
Dim iReturnFuctionID As Integer = 0
Dim tmpFnInfo As New clsFunctionInfo
tmpFnInfo = _objFnXtef(functionlist.SelectedIndex)
iReturnFuctionID = tmpFnInfo.IFunctionNumber
Func = (iReturnFuctionID)
End Sub
And here is the supporting class:
Imports Microsoft.VisualBasic.FileIO
Public Class clsFunctionInfo
Private _idxFunction As Integer
Public Property IdxFunction() As Integer
Get
Return _idxFunction
End Get
Set(ByVal value As Integer)
_idxFunction = value
End Set
End Property
Private _strFunction As String
Public Property StrFunction() As String
Get
Return _strFunction
End Get
Set(ByVal value As String)
_strFunction = value
End Set
End Property
Private _iFunctionNumber As Integer
Public Property IFunctionNumber() As Integer
Get
Return _iFunctionNumber
End Get
Set(ByVal value As Integer)
_iFunctionNumber = value
End Set
End Property
End Class
Public Class clsFunctionXref
Implements System.Collections.IList
Private _colFunctionInfo As New Collection
Private _filePath As String
Public Property FilePath() As String
Get
Return _filePath
End Get
Set(ByVal value As String)
_filePath = value
End Set
End Property
Public Sub New(ByVal filename As String)
_filePath = filename
Dim _idx As Integer = 1
Dim fields As String()
Dim delimiter As String = ","
Dim iFnx As Integer
Using parser As New TextFieldParser(filename)
parser.SetDelimiters(delimiter)
While Not parser.EndOfData
' Read in the fields for the current line
fields = parser.ReadFields()
Try
iFnx = Convert.ToInt16(fields(0).ToString)
Catch ex As Exception
MessageBox.Show("Error reading file. " & ex.ToString, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End Try
Dim objFunction As New clsFunctionInfo
objFunction.IdxFunction = _idx
objFunction.IFunctionNumber = iFnx
objFunction.StrFunction = fields(1).ToString
Me.Add(objFunction)
_idx += 1
End While
End Using
End Sub
Public Function Add(ByVal value As Object) As Integer Implements System.Collections.IList.Add
If _colFunctionInfo.Contains(value.IFunctionNumber.ToString) Then
SyncLock Me.SyncRoot
_colFunctionInfo.Remove(value.IFunctionNumber.ToString)
End SyncLock
ReIndex()
End If
SyncLock Me.SyncRoot
_colFunctionInfo.Add(value, value.IFunctionNumber.ToString)
End SyncLock
End Function
Public Sub Clear() Implements System.Collections.IList.Clear
SyncLock Me.SyncRoot
_colFunctionInfo.Clear()
End SyncLock
End Sub
Public Function Contains(ByVal value As Object) As Boolean Implements System.Collections.IList.Contains
If _colFunctionInfo.Contains(value.IFunctionNumber.ToString) Then
Return True
Else
Return False
End If
End Function
Public ReadOnly Property Count() As Integer Implements System.Collections.ICollection.Count
Get
Return _colFunctionInfo.Count
End Get
End Property
Public ReadOnly Property IsReadOnly() As Boolean Implements System.Collections.IList.IsReadOnly
Get
Return False
End Get
End Property
Public Sub Remove(ByVal value As Object) Implements System.Collections.IList.Remove
If _colFunctionInfo.Contains(value.IFunctionNumber.ToString) Then
SyncLock Me.SyncRoot
_colFunctionInfo.Remove(value.IFunctionNumber.ToString)
End SyncLock
ReIndex()
End If
End Sub
Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Return _colFunctionInfo.GetEnumerator
End Function
Public Sub Insert(ByVal index As Integer, ByVal value As Object) Implements System.Collections.IList.Insert
SyncLock Me.SyncRoot
If _colFunctionInfo.Contains(value.IFunctionNumber.ToString) Then
_colFunctionInfo.Remove(value.IFunctionNumber.ToString)
End If
If index < _colFunctionInfo.Count Then
_colFunctionInfo.Add(value, value.IFunctionNumber.ToString, index - 1)
Else
_colFunctionInfo.Add(value, value.IFunctionNumber.ToString)
End If
End SyncLock
ReIndex()
End Sub
Public Sub RemoveAt(ByVal index As Integer) Implements System.Collections.IList.RemoveAt
SyncLock Me.SyncRoot
If _colFunctionInfo.Count <= index And index > 0 Then
_colFunctionInfo.Remove(index)
End If
End SyncLock
ReIndex()
End Sub
Private Sub ReIndex()
SyncLock Me.SyncRoot
Dim iReIndex As Integer = 1
Dim colTemp As New Collection
For Each obj As clsFunctionInfo In _colFunctionInfo
obj.IdxFunction = iReIndex
colTemp.Add(obj, obj.IFunctionNumber)
iReIndex += 1
Next
_colFunctionInfo.Clear()
For Each obj1 As clsFunctionInfo In colTemp
_colFunctionInfo.Add(obj1, obj1.IFunctionNumber.ToString)
Next
colTemp.Clear()
End SyncLock
End Sub
Public ReadOnly Property IsSynchronized() As Boolean Implements System.Collections.ICollection.IsSynchronized
Get
Return True
End Get
End Property
Public ReadOnly Property SyncRoot() As Object Implements System.Collections.ICollection.SyncRoot
Get
Dim _syncRoot As New Object
Return _syncRoot
End Get
End Property
Public ReadOnly Property IsFixedSize() As Boolean Implements System.Collections.IList.IsFixedSize
Get
Return False
End Get
End Property
Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer) Implements System.Collections.ICollection.CopyTo
For Each obj As clsFunctionInfo In _colFunctionInfo
array(index) = obj
index += 1
Next
End Sub
Public Function IndexOf(ByVal value As Object) As Integer Implements System.Collections.IList.IndexOf
SyncLock Me.SyncRoot
Dim tmpFnInfo As New clsFunctionInfo
Dim tmpFunctionNumber As Integer
Dim tmpidx As Integer = -1
tmpFnInfo = DirectCast(value, clsFunctionInfo)
tmpFunctionNumber = tmpFnInfo.IFunctionNumber
For Each obj In _colFunctionInfo
tmpFnInfo = DirectCast(obj, clsFunctionInfo)
If tmpFunctionNumber = tmpFnInfo.IFunctionNumber Then
tmpidx = tmpFnInfo.IdxFunction
Exit For
End If
Next
Return tmpidx
End SyncLock
End Function
Default Public Property Item(ByVal index As Integer) As Object Implements System.Collections.IList.Item
Get
index += 1
Return _colFunctionInfo(index)
End Get
Set(ByVal value As Object)
End Set
End Property
End Class
I'm sorry that this is so long, but I know that someone on here has some great suggestions on how to handle this because I'm having a little trouble wrapping my head around it. I think I've been starring at it too long.
since you have the text file as an embedded resource, you can open a stream to the file from there, without having to write it to disk. The ResourceReader class should help you.

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