VB.Net Running Threading with Reflected Objects - vb.net

Running into problems creating objects through reflection and then running them on multiple threads.
I just cannot seem to figure out what I need to here:
For Each WorkerNode As XmlNode In oRunSettings.GetWorkerValues
Dim sWorkerName = WorkerNode.Attributes(SETTING_NAME_ID).Value
Dim oWorkerType As Type = Type.GetType(String.Format("Worker.{0}", sWorkerName))
Dim oWorker As Object = Activator.CreateInstance(oWorkerType)
Dim tWorker As Thread = New Thread(AddressOf oWorker.Process)
tWorker.Start()
Next
It is causing errors at the "AddressOf" because Object does not have a method called that. Do I need to do something with an interface?

First of all I want to say that I've never wrote code in VB so I can be completely wrong here but I'll try anyway.
It seems that you hold the created instance as Object instead of it's correct type.
Object does not contain method named Process, hence the error.
try casting the object to the correct type.

I hate when people answer their own question, but while waiting for an answer, I realized that I could just cast the object as its base object, and set the reflection from there. That is working now.

Related

Accessing Dynamic Dims

I am creating what I believe is the way to create dynamic dims e.g.
Dim browser(DataGridView1.Rows(e.RowIndex).Cells(0).Value)
which basically is creating a something like Dim browser(1)
However I am trying to write a test button to call this browser by using:
browser1.load("http://google.com")
and I have even tried
browser(1).load("http://google.com"
I get the browser part underlined.
What is the correct way to reference them?
I'm not sure what the end goal is, but this construct:
Dim browser(1)
Is effectively the same as:
Dim browser(1) as Object
i.e. it's creating an array of Object of length 2, which is fine in that it can hold anything but makes your life pointlessly hard because you then have to cast the contents every time you want to do something with them; it's bad enough storing a single thing (such as a web browser widget) as an Object:
'this is bad
Dim browser as Object = New WebBrowserWidget
Because you have to cast it every time you use it (when Option Strict is On, which is really the only way you should ever program)
DirectCast(browser, webBrowserWidget).Load("http://google.com)
But to then add the indirection of storing it in an array:
'this is worse
Dim browser(1) as Object
browser(0) = New WebBrowserWidget
browser(1) = New WebBrowserWidget
And casting them to use them:
DirectCast(browser(0), webBrowserWidget).Load("http://google.com)
Just give these things a proper type when you declare them, or use type inference by providing something on the right hand side of an = that is a particular type:
'infer the type from the right hand side
Dim browser = New WebBrowserWidget
'or declare, give a type and create a new instance to assign to it
Dim browser as New WebBrowserWidget
Then it's a lot easier to use it, because Intellisense will know it's a browser and offer you help with the methods and properties, such as Load:
browser.Load("http://google.com")
If you code with Option Strict Off then you can store things in an object and just cross your fingers and hope you get everything right when youre coding, but it's like writing javascript - fumbling round eyes closed not knowing whether you got it right til it blows up at runtime:
Dim x as Object = New WebBrowserWidget
x.Load(...) 'don't get any intelllisense for this, but it'll work at runtime
x.Laod(...) 'dont get any compiler error even though this is a typo - it'll just explode at runtime

A null reference could result in runtime

Dim policy_key() As RenewalClaim.PolicyKeyType
policy_key(0).policyEffectiveDt = date_format_string(ld_EffectiveDate)
Getting error at Line2.
An Error occured - Object reference not set to an instance of an object.
Each element of object arrays also needs to be declared as a new object too.
Dim policy_key() As RenewalClaim.PolicyKeyType
Redim policy_key(0)
policy_Key(0) = new RenewalClaim.PolicyKeyType
policy_key(0).policyEffectiveDt = date_format_string(ld_EffectiveDate)
QUICK TIP: When declaring classes structures etc, it is useful to name them so you can see what type they are....
e.g.
cls_Policy_Key for a class
str_Policy_Key for a structure etc.
When you come back to your code after a year.. you will thank yourself for doing so.
Dim policy_key() As RenewalClaim.PolicyKeyType
is part of your problem. When you are declaring policy_key() you are actually declaring it as an array with no elements. If you don't particularly need to use an array, for example, if you don't need to add objects to a particular element number, you might be better using a list and declaring it like this
Dim policy_key As New List(Of RenewalClaim.PolicyKeyType)
This way, you can add items easily without having to resize your array each time - The code is a little longer than Trevor's answer, but less prone to errors when you extend your code -
dim newPolicy_Key as RenewalClaim.PolicyKeyType
newPolicy_Key.policyEffectiveDt = date_format_string(ld_EffectiveDate)
policy_Key.add(newPolicyKey)

convert early binding to late binding without changing object type

This seems like a simple question but I after chasing forums for several hours I think it might be impossible.
I often want to convert a program from early binding to late binding. Usually, it is a vba, visual basic for applications, program that runs under Excel 2010 and windows 7 pro.
For discussion purposes, let’s pretend it is the following.
Sub EarlyBind()
' use IDE > Tools > references > and select “Microsoft Internet Controls”
Dim shellWins1 as shdocvw.shellwindows
Line1: Set shellWins1 = New SHDocVw.ShellWindows
MsgBox TypeName(shellWins1) ' this will display “IShellWindows”
' other code that expects to be working with an IshellWindows object …..
End Sub
In my experience, converting such a program to late binding is sometimes hard.
For instance, I found some forums that suggest I change it to
Set shellwins1 = createobject("Shell.applicaton")
But that creates a IShellDispatch5 object, not an IshellWindows object. That means I have to change other code to accommodate the new object type. And, of course I have to test that other code for subtle differences.
So, my goal is to find a general solution that will allow me to rewrite “Line1” to create the CORRECT object type with late binding. I also wish to avoid the need setting a reference to "Microsof Internet Controls. In other words, I want the code to look like this:
Sub LateBind()
Dim shellWins1 as object
Line1: Set shellWins1 = createobject(“xxxxxx.yyyyyy”).zzzzzz
MsgBox TypeName(shellWins1) ‘ this should display “IShellWindows”
….. other code that expects to be working with an IshellWindows object …..
End Sub
I know how to use the vba IDE to find the dll associated with the object. In this case the dll is Library SHDocVw C:\Windows\SysWOW64\ieframe.dll.
I have installed OleView and can find the associated IshellWindows “magic numbers” for the clsId, TypeLib, and Inteface (for instance the interface is 85CB6900-4D95-11CF-960C-0080C7F4EE85).
But, I don’t know how to convert them into a program id that can be used in line1 in the sample code posted above.
I hope someone here can help.
------ With MeHow's help, I now have the answer! ------
To switch 'set myObj = new xxxx.yyyyy' to late binding for arbitrary object types
Change set myObj = new xxxx.yyyyy
into set myObj = CreateObject("xxxx.yyyyy")
Very often that will work.
But, in the some cases, (e.g. "shDocVw.ShellWindows.") it gives error 429 ActiveX component cannot be created.
When that occurs I AM COMPLETELY OUT OF LUCK. It is impossible to use late binding with that EXACT object class. Instead I must find a substitute class that does approximately the same thing. (e.g. "Shell.Application").
Your short answer is
IShellWindows is an interface.
It
Provides access to the collection of open Shell windows.
Therefore
Take a look at the CreateObject() method.
Note:
Creates and returns a reference to a COM object. CreateObject cannot
be used to create instances of classes in Visual Basic unless those
classes are explicitly exposed as COM components.
IShellWindows is not exposed as a COM component so that's why there is no way to say CreateObject("SHDocVw.IShellWindows")
When you open your registry (regedit) and search for a key type in IShellWindows. If you find anything that means you've found your Prog ID and if you don't find anything it means that nothing like IShellWindows is registered as a prog Id therefore it would make sense to assume that you can't late bind IShellWindows
I bumped into your question trying to find something for myself. But I don't know if you have tried the following -
Set shellwins1 = createobject("Shell.Application")
MsgBox TypeName(shellWins1.Windows)
This answers your question for datatype. It prints IShellWindows for me. I'm not sure though if it could actually solve your purpose for latebinding meaning if this would be the object required though the datatype is what you need.
So, I would advise you to give it a try.
There is a slightly better approach outlined at https://www.experts-exchange.com/questions/28961564/How-to-find-the-class-id-of-an-arbitrary-object-Example-Set-x-CreateObject-New-1C3B4210-F441-11CE-B9EA-00AA006B1A69.html#a41743468.

Instantiating a variable with Nothing, then assigning a New object instance

Looking through some old VB.Net code, I noticed a strange pattern that is making me scratch my head.
Dim objMyObject As Namespace.Child.ChildType = Nothing
objMyObject = New Namespace.Child.ChildType
(There is no additional code between the dimension and the assignment.)
It seems like the preferred style would be to do both on one line, or else skip the = Nothing. As follows:
Dim objMyObject As Namespace.Child.ChildType = New Namespace.Child.ChildType
OR
Dim objMyObject As Namespace.Child.ChildType
objMyObject = New Namespace.Child.ChildType
OR, as suggested by #helrich
Dim objMyObject As New Namespace.Child.ChildType
Is there any particular value to doing it this way, or is this an instance of the original programmer being used to the VB6 way of doing things?
In VB6, dimensioning and instantiating a variable on one line was considered problematic because it would rerun the instantiation (if necessary) when the variable was accessed - effectively, a variable dimensioned in this way could never be tested for Nothing, because a new instance would be created on demand. However, VB.Net does not preserve this convention.
No, this is pointless. The CLR already provides a hard guarantee that variables are initialized to Nothing.
It is otherwise completely harmless, the jitter optimizer will completely remove the code for the assignment. So if the original author preferred that style then that's okay. Maybe he was a former C# programmer that didn't understand the definite assignment rules in that language. VB.NET does some checking too but it isn't nearly as strict. Do check if this is a team standard that you are supposed to follow as well, hopefully not.
In the first example, there's no need to separate the declaration and assignment.
But I was wondering here (a hypothesis): Since you should split this way when you want to persist the variable in the stack when it is assigned in a code block (e.g: If statement), maybe once upon a time this block existed and it was removed keeping a constant association to it.
Its association, though, was not merged with its declaration.
About associating Nothing to an empty variable: I personally like this pattern. :)
It tells myself (in future maintainances) that the variable was declared with an empty (null) value on purpose. It eliminates the doubt that I, maybe, forgot to write the New keyword behind the type.
Ahh, and it will also eliminate a vb.net warning during build.

object reference not set to an instance of object [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 2 years ago.
I have been getting an error in VB .Net
object reference not set to an instance of object.
Can you tell me what are the causes of this error ?
The object has not been initialized before use.
At the top of your code file type:
Option Strict On
Option Explicit On
Let's deconstruct the error message.
"object reference" means a variable you used in your code which referenced an object. The object variable could have been declared by you the or it you might just be using a variable declared inside another object.
"instance of object" Means that the object is blank (or in VB speak, "Nothing"). When you are dealing with object variables, you have to create an instance of that object before referencing it.
"not set to an " means that you tried to access an object, but there was nothing inside of it for the computer to access.
If you create a variable like
Dim aPerson as PersonClass
All you have done was tell the compiler that aPerson will represent a person, but not what person.
You can create a blank copy of the object by using the "New" keyword. For example
Dim aPerson as New PersonClass
If you want to be able to test to see if the object is "nothing" by
If aPerson Is Nothing Then
aPerson = New PersonClass
End If
Hope that helps!
sef,
If the problem is with Database return results, I presume it is in this scenario:
dsData = getSQLData(conn,sql, blah,blah....)
dt = dsData.Tables(0) 'Perhaps the obj ref not set is occurring here
To fix that:
dsData = getSQLData(conn,sql, blah,blah....)
If dsData.Tables.Count = 0 Then Exit Sub
dt = dsData.Tables(0) 'Perhaps the obj ref not set is occurring here
edit: added code formatting tags ...
In general, under the .NET runtime, such a thing happens whenever a variable that's unassigned or assigned the value Nothing (in VB.Net, null in C#) is dereferenced.
Option Strict On and Option Explicit On will help detect instances where this may occur, but it's possible to get a null/Nothing from another function call:
Dim someString As String = someFunctionReturningString();
If ( someString Is Nothing ) Then
Sysm.Console.WriteLine(someString.Length); // will throw the NullReferenceException
End If
and the NullReferenceException is the source of the "object reference not set to an instance of an object".
And if you think it's occuring when no data is returned from a database query then maybe you should test the result before doing an operation on it?
Dim result As String = SqlCommand.ExecuteScalar() 'just for scope'
If result Is Nothing OrElse IsDBNull(result) Then
'no result!'
End If
You can put a logging mechanism in your application so you can isolate the cause of the error. An Exception object has the StackTrace property which is a string that describes the contents of the call stack, with the most recent method call appearing first. By looking at it, you'll have more details on what might be causing the exception.
When working with databases, you can get this error when you try to get a value form a field or row which doesn't exist. i.e. if you're using datasets and you use:
Dim objDt as DataTable = objDs.Tables("tablename")
you get the object "reference not set to an instance of object" if tablename doesn't exists in the Dataset. The same for rows or fields in the datasets.
Well, Error is explaining itself. Since You haven't provided any code sample, we can only say somewhere in your code, you are using a Null object for some task. I got same Error for below code sample.
Dim cmd As IDbCommand
cmd.Parameters.Clear()
As You can see I am going to Clear a Null Object. For that, I'm getting Error
"object reference not set to an instance of an object"
Check your code for such code in your code. Since you haven't given code example we can't highlight the code :)
In case you have a class property , and multiple constructors, you must initialize the property in all constructors.