Can deserialize accept further parameter? - json.net

Usually this is how I created objects
Public Shared Function createBasicSimpleOrder(ammountOfQuoteCurrencyBeingOrdered As Decimal, priceInBasecoin As Decimal, Base As String, Quote As String, exchangeObject As ExchangesClass, isSellingInsteadOfBuying As Boolean, customIdentifier As String) As BasicSimpleOrder
Dim exchangeString = exchangeObject.ExchangeStringName
Dim a = New BasicSimpleOrder(ammountOfQuoteCurrencyBeingOrdered, priceInBasecoin, Base, Quote, exchangeString, isSellingInsteadOfBuying, customIdentifier)
a.initializeComplexObjects(exchangeObject)
Return a
End Function
Basically one of the parameter is an object
exchangeObject As ExchangesClass
That is the only non primitive Object that is a member of BasicSimpleOrder
So after I set up the primitive Public Read Only properties, I called this function.
Public Sub initializeComplexObjects(exchangeObject As ExchangesClass)
_exchangeObject = exchangeObject
If exchangeObject Is Nothing Then Exit Sub
Dim mark = CoinClass.MarketBaseQuoted(exchangeObject.ExchangeStringName, Base, Quote)
If mark Is Nothing Then Exit Sub
setMarket(mark)
End Sub
Now say I want to deserialize
I then do
gridOrderOldState = Newtonsoft.Json.JsonConvert.DeserializeObject(Of futureStateForGrid)(settingsFromBefore)
Basically futureStateForGrid is a class that contain some derived class of BasicSimpleOrder
For that DeserializeObject to work I already set a constructor
Protected Sub New(ammountOfQuoteCurrencyBeingOrdered As Decimal, priceInBasecoin As Decimal, Base As String, Quote As String, exchangeString As String, isSellingInsteadOfBuying As Boolean, customIdentifier As String)
_ammountOfQuoteCurrencyBeingOrdered = ammountOfQuoteCurrencyBeingOrdered
_Base = Base
_Quote = Quote
_priceInBasecoin = priceInBasecoin
_exchangeString = exchangeString
_isSellingInsteadOfBuying = isSellingInsteadOfBuying
_customIdentifier = customIdentifier
'initializeType0(ammountOfQuoteCurrencyBeingOrdered, priceInBasecoin, Base, Quote, exchangeString, isSellingInsteadOfBuying, customIdentifier)
End Sub
The problem is if I use DeserializeObject, I cannot run initializeComplexObjects(exchangeObject As ExchangesClass)
That's because my new (constructor) function does not accept exchangeObject as ExchangeClass as parameter.
If Protected Sub New accept exchangeObject as ExchangeClass as a parameter, newtonsoft won't know which object should be put on parameter. After all ExchangeClass is a complex object and not a primitive type. Hence, they're not really there.
So how can I set the exchangeObject as parameter so the constructor know?

Related

Dim variable as datatype stored in db field

I have database table which has a field called "datatype". It will hold a particular datatype, such as string, integer, classname, etc....
How can I dim a variable using whatever is stored in this field? For example, if the field says "string" I want to effectively say "Dim MyVar as string", but fill in the "string" portion with what's stored in the table. Hope that makes sense. Thanks!
You can create instances from the name of the class. Note, you can't ask for "MyClass1" without the namespace before it. There are some options for getting from "MyClass1" to "Namespace.MyClass1" such as a Dictionary or even putting the full type name in your database.
Module Module1
Sub Main()
' compiler knows mc1 is a IMyClasses
Dim mc1 = CType(getInstanceFromTypeName("ConsoleApplication1.MyClass1"), IMyClasses)
' compiler doesn't know, mc2 is an object
Dim mc2 = getInstanceFromTypeName("ConsoleApplication1.MyClass2")
mc1.Foo()
mc2.foo()
End Sub
Private Function getInstanceFromTypeName(typeName As String) As Object
Dim o As Object
Try
o = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(typeName)
Catch ex As Exception
o = Nothing
End Try
Return o
End Function
End Module
Public Class MyClass1
Implements IMyClasses
Public Sub Foo() Implements IMyClasses.Foo
Debug.Print("MyClass1")
End Sub
End Class
Public Class MyClass2
Implements IMyClasses
Public Sub Foo() Implements IMyClasses.Foo
Debug.Print("MyClass2")
End Sub
End Class
Public Interface IMyClasses
Sub Foo()
End Interface
mc1.Foo() works because mc1 is declared as an IMyClasses, and IMyClasses defines this subroutine. The compiler knows that IMyClasses defines Foo.
mc2.foo() doesn't work with Option Strict On because Foo() is not a member of Object. With O.S.On, the compiler must be able to resolve all function calls at compile time. It works with Option Strict Off however, as O.S.Off allows function calls on Object, but can potentially be dangerous because O.S.Off also allows mc2.asdf(), for example.
Other resources:
Using System.Reflection
Using System.Activator

Convert IEnumerable(Of Object) to class that Implements IEnumerable(Of Object)?

Using VB.NET, I have ths class
Public Class MyCollectionClass
Implements IEnumerable(Of MyClass)
Public Property MadeThisClassCuzINeedToSetThis() As String
' code here
End Class
I want to do this, but get an exception saying I can't do this cast.
Dim objColl As MyCollectionClass
objColl = CType(IEnumerable(Of MyClass), MyCollectionClass)
Can anyone tell me how to get this to work. Thanks.
See this VB.NET/C# casting cheat sheet or the documentation on CType. The major problem is that the first parameter should be the instance to convert, not its type. This should work:
Dim myEnumerable As IEnumerable(Of MyObjectClass) = New MyCollectionClass()
Dim objColl = CType(myEnumerable, MyCollectionClass)
' objColl's type is inferred As MyCollectionClass
(note that as MyClass is a keyword, and I assume you actually have a different class name there, I changed it to MyObjectClass in my example)

Do I Need a Class if I only need 1 Property (at the moment)?

Update: I didn't make it clear but I meant this to be a question about where/how I would use a function to return a list of strings when I'm trying to just work with classes.
I have a class called Account.
I have data access class called AccountDAO.
I have various functions that return lists of objects like GetAllAccounts, GetAccountByID etc.
I want to populate a drop down list with just the account names and nothing else. It's proving rather slow when using lists of objects and databinding them to the dropdownlist.
I feel like I should be using a simple "Select Account_Name From blah" type statement and returning a list of strings but I don't know how to work this into my class and data access class.
How should I handle this predicament?
You can use a list of string,s and bind the list of strings to a dropdownlist no problem... the DDL can support that, just leave out DataTextField and DataValueField props, and it will display the account name as is, which that name would be accessible through the ListItem's Text and Value property.
I like to use objects to be consistent with the rest of the app (which other areas might need a class), and if for some reason you want to add AccountKey later, if you use an object, all you need to do is add a property. Otherwise, if using strings, you'd have to switch up the binding later to point to the object.
HTH.
There is nothing wrong by making a function that only returns a list of strings. YOu could however wonder if it's not better to restrict the number of records you want to put in the list and use some kind of paging.
Assuming that you're using a List<>, you can try something like this:
IEnumerable<string> nameList = accountList.Select(t => t.AccountName);
Or if you need a List:
List<string> nameList = accountList.Select(t => t.AccountName).ToList();
Go with your feelings. Use a datareader to select the list and then load them into an arraylist which can then be bound to the dropdown. Alternately, use something like this method I use to provide both a DisplayMember and a ValueMember which uses a class (with both values) as members of the arraylist. This should give you the general idea. (Note: I normally include this code in a data access class (MyBase) where StartReader, _datRdr, ReadNext and_ReaderValid are a members. But the general idea is intact.)
Public Sub LoadDataSource(ByRef PlantDataSource As PlantSource, Optional ByVal Filter As String = "", Optional ByVal IncludeBlankItem As Boolean = False)
PlantDataSource = New PlantSource
If IncludeBlankItem Then
PlantDataSource.Add(0, "")
End If
If Filter = String.Empty Then
Call StartReader(" Order by PlantName")
Else
Call StartReader(String.Concat(" Where ", Filter, " Order by PlantName"))
End If
If _DatRdr.HasRows Then
While MyBase._ReaderValid
PlantDataSource.Add(PlantId, PlantName)
ReadNext()
End While
End If
Call CloseReader()
End Sub
Private Class PlantListing
Private _PlantList As New ArrayList
Public Sub Add(ByVal PlantId As Integer, ByVal PlantName As String)
_PlantList.Add(New PlantDataItem(PlantId, PlantName))
End Sub
Public ReadOnly Property List() As ArrayList
Get
Return _PlantList
End Get
End Property
End Class
Private Class PlantDataItem
Private _PlantId As Integer
Private _PlantName As String
Public Sub New(ByVal pPlantId As Integer, ByVal pPlantName As String)
Me._PlantId = pPlantId
Me._PlantName = pPlantName
End Sub
Public ReadOnly Property PlantName() As String
Get
Return _PlantName
End Get
End Property
Public ReadOnly Property PlantId() As Integer
Get
Return _PlantId
End Get
End Property
Public ReadOnly Property DisplayValue() As String
Get
Return CStr(Me._PlantId).Trim & " - " & _PlantName.Trim
End Get
End Property
Public Overrides Function ToString() As String
Return CStr(Me._PlantId).Trim & " - " & _PlantName.Trim
End Function
End Class

Can a VBScript function return a dictionary?

I have a dictionary of form data that I want to modify using a function.
function queryCleanForm(myDictForm)
dim arrayKeys
arrayKeys = myDictForm.keys
for i=0 to myDictForm.count-1
myDictForm(arrayKeys(i)) = replace(myDictForm(arrayKeys(i)), "'", "''")
response.write myDictForm(arrayKeys(i))
next
queryCleanForm = myDictForm
end function
The problem is the line queryCleanForm = myDictForm errors as
Wrong number of arguments or invalid property assignment
Is there a way to do this in VBScript?
Try this:
SET queryCleanForm = myDictForm
With objects you need to use SET to tell VBScript that it is an object reference you are assigning not a value type.
Yes, you need to use the SET command:
Set queryCleanForm = myDictForm
You can also use the ByRef or ByVal values in the function. ByVal, the object you sent to a function or sub is copied into private memmory to be used inside the function and discarded after the function is completed. ByRef, the object you sent to a function is referenced to and all manipulations you make, removing keys, setting the object etc, is directly done to the object you sent.
E.g.
Sub test
DIM testDict as variant
call setdict(testDict)
testDict.Add "test", "value"
call addValue(testDict, "test2","another value")
msgbox testDict.Count
Set testDict = Nothing
End Sub
Sub setdict(ByRef in_Dict as Variant)
If Typename(in_Dict) <> "Dictionary" Then
SET in_Dict = CreateObject("Scripting.Dictionary")
end if
end sub
sub addValue(ByRef in_Obj as Variant, ByVal in_Key as String, ByVal in_Value as String)
if not in_Obj.Exists(in_Key) then
in_Obj.Add in_Key, in_Value
end if
end sub
The test sub calls with a variable of type variant to the sub setdict. In the function I validate the type of the object sent to the sub. If the object type is not a dictionary object (which it is not) then the object in_Dict which is actually the testDict object declared in the sub test, will be set to a dictionary object.
To demonstrate the reference better I also included the second sub called addvalue. I pass the object to the function again as reference and add another key to the dictionary object. In the main test sub ill then post the count. In this case there are 2 keys present.

updating properties of a class with dynamic references

Sorry for what is probably a very basic question. I have a vb.net class with properties defined as follows:
Private m_Property1 As String
Public Property Property1() As String
Get
Return m_Property1
End Get
Set(ByVal value As String)
If IsNothing(value) Then
m_Property1 = String.Empty
Else
m_Property1 = value
End If
End Set
End Property
I can then set the values as follows:
classname.Property1 = "myvalue"
How do I set the value of a property that is defined dynmically eg
Dim strPropertyName As String = "Property1"
Hope that makes sense.
Thanks,
Josh
You would use reflection
Dim strPropertyName as string = "Property1"
Dim pi As PropertyInfo = myClass.GetType().GetProperty(strPropertyName)
pi.SetValue(myClass.GetType(), "some string", Nothing)
You want to use Reflection in order to do this. VB.NET provides a way to do this if you know the value at compile-time, but for run-time operations, you need to use the GetType keyword in order to get the type of your class (or, use the GetType method on an instance of it if you don't know it).
Then, with that Type instance, you would call GetProperty, passing the string with the name of the property. It will return an PropertyInfo instance which you then call GetValue on, passing the instance of the object in, which will return an Object which you have to cast back to a type you wish to use (if you are).
VB.NET makes a lot of this easier with the CallByName function.
Also, if you know at compile-time what the name of the property is, you can always cast to object and use VB.NET's inherent late binding:
Dim o As Object = <your object>
o.Property1 = ...
VB.NET will perform the late-binding for you.

Resources