Save reference to private field (vb.net) - vb.net

I'm quite new to VB.NET programming and I have this situation:
I have one class Foo with some private fields (the number can be increased so I want to write some flexible code) and its corresponding public readonly properties. For updating the values of the private fields, I have to read them in a OPC server. When I register to an OPCServer item, I get an integer, called ServerHandle, to identify it. Then, when I read the OPC server, I get several ServerHandles with its corresponding values, in the form of a dictionary (serverHandles as keys).
What I would like to create while creating my object, is a list of helper objects (I have called them Item) with only two public fields, ServerHandle and a reference to a private field, so I could do something like this when I get the dictionay of updates values:
Public Class Foo
Private field1 As Double
Private field2 As Double
Private listOfitems As List(Of Item)
Private Sub UpdateValues(dictionaryOfValues As Dictionary(Of Integer, Double))
For Each item As Item In listOfitems
item.Field = dictionaryOfValues(item.ServerHandle)
Next
End Sub
End Class
Public Class Item
Public Field As Object
Public ServerHandle As Integer
End Class
I know it is not possible to save a reference to a private field like this... but I would like to know if there is some way of doing something similar to what I'm trying.
If not... do you have any suggestions about how could I do this? (I have the feeling that I'm complicating my solution needlessly).
Thank you very much!

You need some type of publicly exposed object on your Foo class, I suggest making a read-only public property for the listOfItems, like this:
Public Class Foo
Private field1 As Double
Private field2 As Double
Private listOfitems As List(Of Item)
Public Property ListOfItems() As List(Of Integer)
Get
Return listOfitems
End Get
End Property
Private Sub UpdateValues(dictionaryOfValues As Dictionary(Of Integer, Double))
For Each item As Item In listOfitems
item.Field = dictionaryOfValues(item.ServerHandle)
Next
End Sub
End Class

Related

How to synchronise update of an attribute that belongs to a module and a class

I'm new to vb.net, so forgive me if the question sounds awfully elementary to many of you. It is about maintaining objects contained in different classes/modules. Currently I have a class called aggregated_SI. Below is the definition for aggregated_SI
Public Class Aggregated_SI
Private _identifier As Integer
Private _From_Firm As String
Private _From_Account_Number As String
Private _To_Account_Number As String
Private _To_Firm As String
Private _Security_Code As String
Private _Quantity As Integer
Private _Settlement_Amount As Decimal
Private _Settlement_Ccy As String
End class
In my module, I have defined an attribute:
Private settlement_Instructions as List(Of Aggregated_SI)
As you can see, Aggregated_SI has various attributes, among them are from_account_number and to_account_number which actually refers to a name of another class account. The Account class has the following attributes:
Public Class Account
Private _account_Number As String
Private _security_Holding As Dictionary(Of String, Integer)
Private _deliver_SIs As Dictionary(Of Integer, Aggregated_SI)
Private _receiving_SIs As Dictionary(Of Integer, Aggregated_SI)
End class
the _deliver_SIs and _receiving_SIs are dictionary that contains the _identifier attribute from Aggregated_SI class as its key and aggregated_SI object as its value. Now, each account contains various aggregated_SIs object which are the subset of the attribute settlement_Instructions
The problem is, as I modify the Aggregated_SI objects inside the settlement_Instructions list, how do I ensure that the various aggregated_SI objects which are contained in _deliver_SIs and _receiving_SIs to be simultaneously updated at the same time? I've tried updating the corresponding SIs in _deliver_SIs and _receiving_SIs separately as I update the aggregated_SI inside settlement_Instructions but this feels redundant and it makes the code not easily read. Any suggestion as to how to approach this problem? Thanks!

Is it possible to create a dictionary of an entity and refer to it in the data layer

I have what is in effect a lookup table in my database upon which my entity model has been based. I would like to refer to this as I respond to OnPropertyChanged events for a particular entity. Given that there could be hundreds of requests to this table I figured that it would be more efficient to create a dictionary from that lookup table and refer to that instead. To that end I have a partial class for mty entities to which I have added the following.
Imports System.Data.Entity
Partial Public Class FireTrackerEntities : Inherits DbContext
Private _defUnitsOfMeasurement As Dictionary(Of Int16, string)
Public Property DefUnitsOfMeasurement As Dictionary(Of Int16, string)
Get
Return _defUnitsOfMeasurement
End Get
Set(ByVal Value As Dictionary(Of Int16, string))
_defUnitsOfMeasurement = Value
End Set
End Property
Public Sub New()
MyBase.New()
CreateDictionaries()
End Sub
Private Sub CreateDictionaries()
Dim ft As DbSet(Of FireTrackerModel.ExtinguisherType)
For Each p In ft
DefUnitsOfMeasurement.Add(p.ExtinguisherTypeId,p.DefaultUnitOfMeasurement)
Next
End Sub
The code compile but in the entity where I wish to refer to this dictionary I can't see it. So Is this entirely the wrong approach or have I missed something?
Thanks
Would you not just do something like this to create a Dictionary:
myDbContext.SomeEntities.ToDictionary(Function(e) e.Id)

Setting Up These Types While Keeping It Properly Structured

I'm completely stuck in a situation and I have no idea on where to go from here. I'm creating a very large project, so my goal is to keep the code itself as clean as possible and keeping as many hacks as possible out of the mix.
Here is the situation.
I have a class called Woo_Type, it is the parent of my many derived classes.
Public MustInherit Class Woo_Type
Private Shared TypeList As New Dictionary(Of String, Woo_Type)
Public MustOverride Sub SetValue(ByVal val As Object)
Public MustOverride Function GetValue() As Object
Public Shared Function GetTypeFromName(ByVal name As String) As Woo_Type
Return TypeList(name)
End Function
Public Shared Sub AddType(ByVal name As String, ByVal def As Woo_Type)
TypeList.Add(name, def)
End Sub
End Class
I have many classes that Inherit from Woo_Type that have similar structures to this:
Public Class Woo_tpInt
Inherits Woo_Type
Private value As Integer = 0
Public Overrides Function GetValue() As Object
Return value
End Function
Public Overrides Sub SetValue(val As Object)
value = val
End Sub
End Class
I want to be able to do things like:
Woo_Type.GetTypeFromName("int")
And have it return something like the class or something...
At this point I'm really confused as to what I want and I didn't know if anybody had any suggestions. To make sure that GetTypeFromName worked correctly, I had in an Initializer sub the following:
Public Sub InitializeTypes()
Woo_Type.AddType("int", Woo_tpInt)
Woo_Type.AddType("String", Woo_tpInt)
End Sub
But I quickly realized that-that obviously doesn't work either.
So this may seem confusing but I'm basically wondering how to better structure this so that everything works...
What do you want to do with the result? Are you sure you don't simply need generics?
Public Class WooType(Of T)
Public Property Value As T
End Class
Public Class Test
Public Sub Foo()
Dim int As New WooType(Of Integer)
int.Value = 42
Dim str As New WooType(Of String)
str.Value = "Forty-Two"
End Sub
End Class
If what you want to do is get the type itself (as opposed to an object), I would recommend using reflection rather than trying to reinvent the wheel. For instance, to get the Woo_tpInt type, you could do this:
Dim a As Assembly = Assembly.GetExecutingAssembly()
Dim t As Type = a.GetType("WindowsApplication1.Woo_tpInt") ' Change WindowsApplication1 to whatever your namespace is
If you want to use a shorter name like "int" to mean "WindowsApplication1.Woo_tpInt", you could create a dictionary to store the translation table, for instance:
Dim typeNames As New Dictionary(Of String, String)
typeNames.Add("int", GetType(Woo_tpInt).FullName)
Dim a As Assembly = Assembly.GetExecutingAssembly()
Dim t As Type = a.GetType(typeNames("int"))

VB Polymorphism Constructors Default and Properties. Similar Class to Listbox

I've been banging my head against a wall for sometime on this one.
I'm trying to create a class for storing data on People with another class to store their Bank Transactions.
Ideally, this all be hidden away and leave only simple statments, declarations and functions available to the programmer. These will include:
Dim Clients As New ClientList
Clients.Count 'readonly integer
Clients.Add("S")
Clients.Refresh()
Clients(n).Remove()
Clients(n).Transaction.Add()
Clients(n).Transaction(n).Remove()
I know this is possible as these exist in the Listbox Class though can't figure out how it's done.
Any help would be appreciated.
Thanks in advance!
Create a Transaction and a Client class
Public Class Transaction
'TODO: Implement Transaction
End Class
Public Class Client
Public ReadOnly Transactions As List(Of Transaction) = New List(Of Transaction)
Public Sub New(ByVal name As String)
Me.Name = name
End Sub
Public Name As String
End Class
Create a ClientList class
Public Class ClientList
Inherits List(Of Client)
Public Overloads Sub Add(ByVal name As String)
Add(New Client(name))
End Sub
Public Sub Refresh()
' Do what ever you want Refresh to do
End Sub
End Class
You can then use the client list like this
Dim clients As New ClientList
clients.Add("S")
' Or
clients.Add(New Client("T"))
Dim n As Integer = clients.Count
Dim m As Integer = clients(0).Transactions.Count
clients.Refresh()
clients.RemoveAt(5)
clients(n - 1).Transactions.Add(New Transaction())
clients(n - 1).Transactions.RemoveAt(2)
Dim name As String = clients(0).Name
Dim client As Client = clients(0)
Use the generic List(Of T) class, specialized to hold your Client objects. It already provides all of the methods you want without your having to write a single line of code!
So you would first write a Client class that contained all of the properties (data) and methods (actions) relating to a "client":
Public Class Client
Public Property Name As String
Public Property AmountOwned As Decimal
Public Sub Bill()
BillingManager.BillClient(Me)
End Sub
' ... etc.
End Class
Then, you would create the List(Of T) to hold all of your instances of the Client class:
Dim clients As New System.Collections.Generic.List(Of Client)
If, for whatever reason, you needed to specialize the behavior of the Add, Remove, etc. methods provided by the collection class, or add additional methods, you would need to change strategies slightly. Instead of using List(Of T), you would inherit from Collection(Of T) and create a custom collection class like so:
Public Class ClientCollection
Inherits System.Collections.ObjectModel.Collection(Of T)
' ... customize as desired ...
End Class
The WinForms ListBox class doesn't do it exactly like this because it was written before generics were introduced to the framework. But since they're here now, and you should always use them when possible, you can completely ignore how WinForms does things.

Generic Collections

In VB6, there used to be a Collection data type that would allow retrieval of an item in the collection by either its key or its ordinal. However, it wasn't strongly typed.
Now, with VB.Net, I am looking for a suitable replacement that is strongly type and could be used with a generic collection.
This is a simple example of what I want to do. The only problem is that the underlying collection class, BindingList, does not support efficient retrieval of an item by an alpha key, so I have to loop through the elements to get the item I am looking for. For large collections, this is not efficient.
I have looked though the various Collection type classes and have found no suitable replacement.
This is what I want to do, except for the looping that is done with the Item property.
Rather than just saying "Use Hash tables" or something like that, if you could, please include the detailed out as I have done for the short example below.
Public Class Car
Public Sub New(ByVal keyName As String, ByVal property1 As String)
_KeyName = keyName
_Property1 = property1
End Sub
Dim _KeyName As String
Public Property KeyName() As String
Get
Return _KeyName
End Get
Set(ByVal value As String)
_KeyName = value
End Set
End Property
Public _Property1 As String
Public Property Property1() As String
Get
Return _Property1
End Get
Set(ByVal value As String)
_Property1 = value
End Set
End Property
End Class
Public Class Cars
Inherits System.ComponentModel.BindingList(Of Car)
Public Overloads ReadOnly Property Item(ByVal key As String) As Car
Get
For Each CurrentCar As Car In Me.Items
If CurrentCar.KeyName = key Then
Return CurrentCar
End If
Next
Return Nothing
End Get
End Property
End Class
I believe you're looking for Dictionary<TKey, TValue>. In fact, if you do want your own collection class that's strongly typed and isn't (itself) generic, if you change your parent class to Dictionary<string, Car>, you should be all set. This all does, of course, assume that you add the cars to the collection with an explicit string key. If you want the lookup to be based on the value of a property in the collection, you'd do better either using or inheriting from List<Car> and using LINQ to query the list. You could then have...
Public Overloads ReadOnly Property Item(ByVal key As String) As Car
Get
Return (from c in Me where c.KeyName = key select c).SingleOrDefault()
End Get
End Property
Do you really need both access by key AND index?
If you do not, then use a Dictionary(Of String, Car), and use
- MyCol.Items("XXX") to retrieve an item by key (or the shorthand MyCol("XXX"))
- MyCol.ContainsKey("XXX") to test if a key exists in the collection
- For Each Entry as KeyValuePair(Of String, Car) in MyCol if you want to enumerate all objects AND their key
- For Each Entry as Car in MyCol.Values if you want to enumerate the entries without consideration for the key
If you need both access by index and key, I'm afraid your best bet is to use a List(of Car) and a Dictionary(of Car) rolled into one custom collection class, because I believe they went away from that kind of collection which is not really all that useful for most problems.
This is what I am thinking is my best solution. I welcome comments for a better way!
Imports Microsoft.VisualBasic
Public Class Car
Implements Xs(Of Car).IKeyName
Private _KeyName As String
Public Sub New(ByVal keyName As String, ByVal property1 As String)
_KeyName = keyName
_Property1 = property1
End Sub
Public Property KeyName() As String Implements Xs(Of Car).IKeyName.KeyName
Get
Return _KeyName
End Get
Set(ByVal value As String)
_KeyName = value
End Set
End Property
Public _Property1 As String
Public Property Property1() As String
Get
Return _Property1
End Get
Set(ByVal value As String)
_Property1 = value
End Set
End Property
End Class
Public Class Cars
Inherits System.ComponentModel.BindingList(Of Car)
Public Overloads ReadOnly Property Item(ByVal key As String) As Car
Get
For Each CurrentCar As Car In Me.Items
If CurrentCar.KeyName = key Then
Return CurrentCar
End If
Next
Return Nothing
End Get
End Property
End Class
Public Class X
Private _KeyName As String
Public Property KeyName() As String
Get
Return _Keyname
End Get
Set(ByVal value As String)
_Keyname = value
End Set
End Property
End Class
Public Class Xs(Of X)
Inherits Hashtable
Interface IKeyName
Property KeyName() As String
End Interface
Public Shadows Sub Add(ByVal item As IKeyName)
MyBase.Add(item.KeyName, item)
End Sub
Public Shadows ReadOnly Property Item(ByVal key As String) As x
Get
If Me.ContainsKey(key) Then
Return MyBase.Item(key)
Else
'If I mispell a key, I don't want to end up creating a new mispelled version, I want an error
Throw New Exception("Element with key " & key & " is not found")
End If
End Get
End Property
End Class
Public Class Cars2
Inherits Xs(Of Car)
End Class
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim MyCar As New Car("key1", "prop1")
'First approach
Dim MyCars As New Cars
MyCars.Add(MyCar)
Dim RetrievedCar As Car = MyCars.Item("key1") 'Inefficient retrieval by key (uses looping)
'Second approach
Dim Cars2 As New Cars2
Cars2.Add(MyCar)
Dim RetrievedCar2 As Car = Cars2.Item("key1") 'Can now efficiently retreive an item by its key
End Sub
The OrderedDictionary in the System.Collections.Specialized namespace can be accessed by index and by key, if you ever need that. But looking at your solution, it looks like a standard Dictionary, but less efficient because it forces a string type for keys.
Is there any reason you can't use the Dictionary .NET provides you, or another collection type that's already in .NET like OrderedDictionary?