Serializing shared field - vb.net

I have one class with a private static (shared, since I'm in VB.NET) field and its associated public static property, since it stores one variable that should be the same to all the instances of this class. So far, so good.
The problem arrives when trying to binary serialize these kind of objects, since this shared field is nos being properly stored and returns to its default value when deserializing.
I suppose this is the expected behaviour, so my question is... how can I make a shared field persistent?
I have read some comments to similar questions that say that this is a bad design, but it really makes sense (AFAIK) in my case, since this variable should be the same to all the object, but can be changed by the user and therefore should be stored.
Can you suggest another way of doing it?
Thanks!
EDIT: (sorry, I was in a hurry and couldn't complete my question until now)
My Class looks like this:
Public MustInherit Class NitrogenController
Private _active As Boolean
Private Shared _controlInterval As TimeSpan
Private _lastControlTime As Date
Public Property Active() As Boolean
Public Shared Property ControlInterval() As System.TimeSpan
'other properies that must be persisted
Public Function Control() As Boolean
If Not Now > _lastControlTime.Add(_controlInterval) Or Not _active Then
Return False
Else
DoControl()
_lastControlTime = Now
Return True
End If
End Function
End Class
So, the problem is that I can have several nitrogen controllers, but they should all have the same _controlInterval. That's the reason why I used a shared variable for this. But it does not preserve its value after serialization/deserialization. So... any ideas about how to do this?
Thanks!

Related

Why to use GET & SET methods while defining properties in VB.Net?

I am bit confused over the need to use GET & SET methods in VB.net. I want to discuss two cases in this connection: firstly when we declare the property as PUBLIC and next when we declare the property as PRIVATE.
What is I find is when I define a property as public I can directly set and access the values of that property without using the GET/SET methods --- quite simple: See below
Module Program
Sub Main()
Dim t As New test()
t.name = "Roy" 'Label 1
Console.WriteLine("t.name = {0}", t.name)
Console.ReadLine()
End Sub
End Module
Class test
Public Property name() As String
End Class
When I declare that same property as private, as shown below, I can still set and access the value of private property by simply using a constructor and a public subroutine. See below:
Module Program
Sub Main()
Dim t As New test()
t.printValue()
Console.ReadLine()
End Sub
End Module
Class test
Private Property Name() As String
Sub New()
Name = "Roy" 'Label 2
End Sub
Public Sub printValue()
Console.WriteLine("Value stored in NAME is: {0}", Name)
End Sub
End Class
So my question is why at all do we need to use the GET/SET methods? I understand that whenever an assignment happens to a property the SET method is implicitly called...but can you please help me understand cases where we MUST explicitly use the GET/SET methods? Or it is that using GET/SET is more of a choice? Validation is one thing that can be added easily at a later stage if one uses GET/SET but then is that the only reason? PLs give your views.
Also, I came across the following two related questions in stackoverflow (for different languages though): Links below:
Why to use getter and setter methods to set class properties?
Why use getters and setters/accessors?
But i could not understand most of the reasons justifying the usage of the GET/SET methods. For example if we dont use the GET/SET method then we are exposing the property to the outside world - meaning it can be directly accessed from outside the class. But then this is true only for PUBLIC properties as PRIVATE properties cannot be directly accessed from outside the class. Similarly in the second link the author mentions the following as a reason to use GET/SET: Providing a debugging interception point for when a property changes at runtime - debugging when and where a property changed to a particular value can be quite difficult without this in some languages. What exactly does this mean --- any simple real life example?
A property is a wrapper around a field, i.e., a class or struct variable. It provides a getter and/or a setter method to access this variable. (You can also have a read-only property returning the result of a simple evaluation not bound to a single field.)
The getters and setters are implicitly called when reading from, respectively writing to properties.
So, the question is not whether to use getters and setters or not, but whether to access fields directly or via a property.
You can declare a property like this, by declaring a field and writing the getter and setter explicitly.
Private _prop1 As String ' Backing field
Public Property Prop1() As String
Get
Return _prop1
End Get
Set(ByVal value As String)
_prop1 = value
End Set
End Property
or use an Auto-Implemented Property
Public Property Prop1 As String
Both declarations are equivalent. The auto-implemented property implicitly declares a backing field and implements the getter and the setter accordingly.
It can make sense to declare a property as private when you use it only inside the class where it is declared. This still provides the advantages described in the links you provided because this property still hides the details of accessing a field, does validations, etc.; however, it does not forbid the direct access to the backing field inside the class. So, you need to be more disciplined with private properties.
What does a property mean for debugging? You can easily set a breakpoint inside a getter or setter to detect accesses to a property. You cannot set a breakpoint on a field because a field is never executed. It is just a declaration.
You can also add a System.Diagnostics.Debug.Writeline("=====> test") (writes to the Output window) or do some logging in getters and setters.
See also: Tutorial: Learn to debug Visual Basic code using Visual Studio
When using Windows Forms Data Binding or WPF Data Binding properties are required. They also allow change notification.
Dynamically Calculated Values
I didn't read those links, but one reason you might want to implement your own getters & setters is that you may want to return something that requires some type of calculation or manipulation. For example, suppose you have item Sale with properties RawPrice, SalesTax, and FinalPrice. However, you need/choose to dynamically calculate the final price (based on variable sales tax) each time. So you first set the RawPrice, and then query FinalPrice, which returns RawPrice + SalesTax, but SalesTax gets dynamically calculated based on some other property like country of origin etc.
Alternate View of Data
Another reason you might want to do this is to provide another view of the same core data. For example, if your data was an HTML page, perhaps one property returns the normal string value, while another "no-HTML" Property has a custom Getter that performs some regex to remove all HTML tags and return a plain-text variation. This allows you to keep all related code inside of a sub-assembly, rather than having your main program do various manipulations.
Code Portability
This can make your life a lot easier down the road because of code portability. Your code is now more easily re-usable in other projects, since all you need is that one assembly.
Private Variables vs Properties
If I'm doing something that calls for a class with properties like that, there's good chances it's going to have methods, too. Those methods are almost always going to require creating private variables that nothing outside the assembly needs to know about. However, in such cases, they are not going to be private properties but rather simply private variables. For example, instead of Private Property Name() As String, with its implied auto-implemented backer variables with getters & setters, I would instead just say Private Name() As String, which would be equivalent to Dim Name() As String. You can use variables, constants etc. within your class just as you normally would, and, by default, the rest of the world won't know anything about them.
I'm not sure why you'd use a private Property. Maybe there's a good reason; I just don't know what it is. Most of the time, a private variable is probably what you really want. If you think there's a reason that you actually need a Private Property, I'm curious to hear your thinking on it. (I'm always open to a new way of thinking!)
History
Auto-implemented properties were not present in Visual Basic .NET for many years. In the past, you had no choice but to use GET/SET. So it's a more recent development for VB.NET to be able to simply declare a property as you do in your first code example, and for the runtime to automatically generate the backer variables.

Initialize a value for a shared property

I want to use a counter for how many objects are created from a single class, so I thought that a Shared Property would be the way to go. But, VB doesn't like that and says, "Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class"
Private _Length As Integer = 0
Public Shared Property Length As Integer
Get
Return _Length
End Get
Set(value As Integer)
_Length = value
End Set
End Property
Is there a way to initialize a shared variable, in this case to zero, and have the Property still function correctly. I used the Java get/set methodology (getLength()/setLength())and that worked fine, but I'm sure that it would be frowned up by VBers.
Also, using two variables to get/set one that is actually used seems a bit redundant. I see why it is used in the VB methodology because of the recursion that happens, but it does look strange.
The backing field _Length must also be shared.
Private Shared _Length As Integer = 0
using two variables to get/set one that is actually used seems a bit
redundant.
You don't have two variables just one which is _Length, a property just manages how you can access that variable. Note that even auto implemented properties like this use a backing-field:
Public Property Length As Int32
You just don't see it since it will be generated for you.

Expose .NET DataTable properties to VBA via COM Interface

I am trying to create a .Net DLL basically as an abstraction layer for database connections; it is going to replace a current DLL we have that is written in VB6 and I am trying to match the current functionality as much as possible.
Anyway, the essential issue I am having is that I can't find a way to get .Net classes like DataColumnCollection or DataColumn to display in the VBA Interpreter -- It may say, for example, "Column" with the type "MarshalByValueComponent," but the value will be "No Variables".
I can get it to work if I completely re-create both classes (i.e. Fields as a collection of field, which inherits from DataColumn, and then define an interface for both), but that seems like a lot of added overhead for what (should be?) a pretty simple idea. I feel like I am just missing something very simple with the way the marshaller is handling the DataColumn class.
A lot of the stuff I am finding online is on how to convert a DataTable or DataReader to a legacy ADODB Recordset, but that also would add a lot of overhead... I'd rather leave it as a DataTable and create a COM interface to allow VBA to interact with it; that way if, for example, they want to write the table to an excel sheet, I wouldn't be duplicating work (convert to ADODB recordset, then read/write to excel sheet. You'd need to iterate the entire table twice...)
Sorry for the book-length explanation -- I felt the problem needed a bit of clarification since the root-cause is trying to match legacy functionality. Here is an example of my current interface that does not work:
Public Interface IDataTable
ReadOnly Property Column As DataColumn
End Interface
<ClassInterface(ClassInterfaceType.None)> _
<System.ComponentModel.DesignerCategory("")> _
<ComDefaultInterface(GetType(Recordset.IDataTable))> _
<Guid("E7AFBBB6-CB20-44EC-9CD2-BC70B94CD8B7")> _
Public Class Recordset : Inherits Data.DataTable : Implements IDataTable
Public ReadOnly Property Column As DataColumn Implements IDataTable.Column
Get
Return MyBase.Columns(0)
End Get
End Property
Note: I originally tried the property Columns as DataColumnCollection which returned MyBase.Columns. That came through as an Object, instead of MarshalByValueComponent, but was also empty. I know MyBase.Column(0) has a value, because I can put Msgbox(MyBase.Columns(0).ColumnName) right above the return in the get and it pops up fine (don't judge; this is way easier than using a debugger for this)...
I wouldn't mind just defining them both, but I can't inherit DataColumnCollection and the COM interface already sucks at dealing with generics. Is there any other way around this without re-inventing the wheel?
Thanks for your help!
I just spent the last 3 weeks doing something eerily similar.
I ended up making two .NET assemblies:
A pure .NET assembly that talks to the datastore (for use by .NET apps).
A "COM Interop" assembly that wraps the first assembly and adds the COM overhead (ADODB references and COM-Visible interfaces).
I call the second assembly from Excel VBA using the VSTO "AddIn.Object" property.
I ended up converting System.Data.DataTables to ADODB.Recordsets as you mentioned. Getting .NET and VBA talking about anything other than primitive types was beyond-frustrating for me. In fact, I ended up serializing some objects as JSON so the two worlds could communicate.
It does seem insane, but I reinvented the wheel.
I followed this MSDN article to make my .NET code callable by VBA.
I used this Code Project article (I'm sure you've seen) to convert to Recordset*.
I let the frameworks handle string, integers, etc.
For all other data types I used Json.Net and a custom VBA class to do JSON serialization.
*Converted article to VB.Net and added some extra error handling.
Okay, this probably isn't the most elegant (or complete, at this point) solution; but I think it's the route I am going to go.
Instead of converting the whole thing to an ADODB Recordset (and duplicating any iterations), I just threw out the DataTable class entirely and wrote my own Recordset class as a COM Wrapper for the a generic Data Reader (via the IDataReader interface) and added a new Field class to manage the type conversion and set up Fields as an array of Field (since interop hates generics)
It basically creates a forward-only ADODB Recordset (same limitations) but has the benefit of only loading one row at a time, so the bulk of the data can be handled as managed code until you know what they want to do with it (I'm going to add methods for ToArray, ToAccessDB, ToFile, etc that use the reader) while still allowing the ability to iterate through the Recordset from excel/access/vbscript/vb6 (if that's really what they want to do.. mostly needed that for legacy support anyway)
Here is an example, in case anyone else has to do this again; somewhat modified for brevity:
Public Interface IRecordset
ReadOnly Property CursorPosition As Integer
ReadOnly Property FieldCount As Integer
ReadOnly Property Fields As Field()
Function ReadNext() As Boolean
Sub Close()
End Interface
<System.ComponentModel.DesignerCategory("")> _
<ClassInterface(ClassInterfaceType.None)> _
<ComDefaultInterface(GetType(IRecordset))> _
<Guid("E7AFBBB6-CB20-44EC-9CD2-BC70B94CD8B7")> _
Public Class Recordset : Implements IRecordset : Implements IDisposable
Private _Reader = Nothing
Private _FieldCount As Integer = Nothing
Private _Fields() As Field
Public ReadOnly Property CursorPosition As Integer Implements IRecordset.CursorPosition...
Public ReadOnly Property FieldCount As Integer Implements IRecordset.FieldCount...
Public ReadOnly Property Fields As Field() Implements IRecordset.Fields...
Friend Sub Load(ByVal reader As IDataReader)
_Reader = reader
_FieldCount = _Reader.FieldCount
_Fields = Array.CreateInstance(GetType(DataColumn), _FieldCount)
For i = 0 To _FieldCount - 1
_Fields(i) = New Field(i, Me)
Next
End Sub
'This logic kinda sucks and is dumb.
Public Function ReadNext() As Boolean Implements IRecordset.ReadNext
_EOF = Not _Reader.Read()
If _EOF Then Return False
_CursorPosition += 1
For i = 0 To _FieldCount - 1
_Fields(i)._Value = _Reader.GetValue(i).ToString
Next
Return True
End Function
From here you just need to define some type like Field or Column and add an interop wrapper for that type:
Public Interface IField
ReadOnly Property Name As String
ReadOnly Property Type As String
ReadOnly Property Value As Object
End Interface
<System.ComponentModel.DesignerCategory("")> _
<ClassInterface(ClassInterfaceType.None)> _
<Guid("6230C670-ED0A-48D2-9429-84820DC2BE6C")> _
<ComDefaultInterface(GetType(IField))> _
Public Class Field : Implements IField
Private Reader As IDataReader = Nothing
Private Index As Integer = Nothing
Public ReadOnly Property Name As String Implements IField.Name
Get
Return Reader.GetName(Index)
End Get
End Property
Public ReadOnly Property Value As Object Implements IField.Value
Get
Return Reader.GetValue(Index)
End Get
End Property
Public ReadOnly Property Type As String Implements IField.Type
Get
Return Reader.GetDataTypeName(Index).ToString
End Get
End Property
Sub New(ByVal i As Integer, ByRef r As IDataReader)
Reader = r
Index = i
End Sub
End Class
All of this is rather silly, but it seems to work well.
Note: I've only been using .Net for about 4 days now, so this might be terrible, please feel free to comment on anything extremely stupid I might be doing.

What to do to prevent God Object?

I know that it is poor programming and architecture when you have a class object that is only to be used in one place. But I've also been warned about creating an object that is all powerful and that can do too much. So how do I break this down? Here is an example of what I mean - please don't take these things literal as this is only an example.
Anyway I have an object that I am working with which is rather complex. A lot of information is stored in this object and it can perform much manipulation on the data. So, let's call this object Earth.
Public Class Planet
Private _population As UInteger = 0
Public ReadOnly Property Population() As UInteger
Get
Return _population
End Get
End Property
Public Overridable Sub CreatePerson(Optional ByVal numberOfPeople As Integer = 1)
_population += numberOfPeople
End Sub
End Class
Simple enough so far. But I could go on and on with the many things that object could possibly perform. So, in order to keep things from getting too complex I broke down "activites" that would happen during the day and during the night by creating two other Objects: Day and Night (these two are not shown). So now I have an updated Planet class.
Public Class Planet
Private _population As UInteger = 0
Private _day As New Day
Private _night As New Night
Public ReadOnly Property Day() As Day
Get
Return _day
End Get
End Property
Public ReadOnly Property Night() As Night
Get
Return _night
End Get
End Property
Public ReadOnly Property Population() As UInteger
Get
Return _population
End Get
End Property
Public Overridable Sub CreatePerson(Optional ByVal numberOfPeople As Integer = 1)
_population += numberOfPeople
End Sub
End Class
Now, these two classes - Day and Night - will never be used outside of the Planet class. Is this a good way to organize my methods and attributes for this "parent" class Planet? How else would I neatly organize similar?
I've read about refactoring but I don't think this helps my case. I like the idea that I can call on an Planet object like this: Earth.Night.BlowUpMoon.
Think in terms of discoverability. If someone else were to use your object would they know that they have to go to a specific time of day to blow up the moon, which is the same as BirthdayCard.September25th.Send()? Any by "someone else" I also include you in 6 months. Are you organizing for the sake of organizing or are you putting similar methods and properties together in a way that makes sense?
Although your example is contrived, this situation is common practive in Domain Driven Design. Your Planet class would be an aggregate - a root object that manages its own internal entities. Outside the aggregate boundary all interaction is via the root aggregate object.
Refactor your class and split it to several smaller classes, each with a single responsibility. It doesn't matter that each of them will only be used once - the code will still be better, easier to understand, and far more testable.

Vb.Net scoping question - private fields

I have been looking at a class that has a method that accepts a parameter that is of the same type of the class containing the method.
Public Class test
private _avalue as integer
Public Sub CopyFrom(ByVal from as test)
_avalue = from._avalue
End Sub
End Class
When used in code
a.CopyFrom(b)
It appears that instance "a" has visibility to the private members of the passed in instance "b" and the line
_avalue = from._avalue
runs without error copying the private field from one object instance to the other.
Does anyone know if this is by design. I was under the impression that a private field was only accessible by the instance of the object.
The private scope is related to the type not the instance. So yes, this is by design.
The class test has knowledge about the private parts of itself, so it can use those parts also on other instances of the same type.
You are writing something similar to to a copy constructor.
Since the copying method/function is being written inside of the same class, it will have access to private variables of any instance of its own class.