Script Task : write 2 classes and access Global variable - vb.net

Can i write 2 classes for one Script Task editor in SSIS(2008). I tried to access the global variable like below. I created 2 classes and it doesn't show any compile error, but i couldn't access the global variable in class2 which was assigned as 2 in class, ScriptMain. Please suggest.
Imports System
Imports System.Data
Class ScriptMain
Dts.Variables("var").Value = 2
End Class
Class class2
Dim var2 As String
var2 = Dts.Variables("var").Value
End Class

Disclaimer - I don't know anything about SSIS, but ...
You can't use Dim statements in the body of a class - they need to be in a method in .net.
There are special methods called constructors (New), that get called when a class is instantiated though, so try
Imports System
Imports System.Data
Class ScriptMain
public sub new()
Dts.Variables("var").Value = 2
end sub
End Class
Class class2
public function GetGlobal() as string
Dim var2 As String
var2 = Dts.Variables("var").Value
return var2
end function
End Class
You'd need to do Dim x as new class2() somewhere and then you can do a call to x.GetGlobal(). Since GetGlobal doesn't make use of any instance state, you could just make it shared.
Beyond that, it's not clear as to what you are trying to accomplish with specificity.

Related

How do I call a subroutine from a string variable?

Using VB.Net 4 and VS2012
I have a Module with some logic in it like this:
Module Mod1
If x = 1 then
Mod2("Mod3","save_it")
else
Mod2("Mod4","edit_it")
end if
End Module
Module Mod2(which_mod, which_action)
' call the correct subroutine
which_mod.which_action()
End Module
How do I use the strings to call the correct subroutine from different modules?
Look at the System.Reflection namespace, it contains a class called MethodInfo.
You can obtain the MethodInfo, for a given object, using the method name, then invoke it:
Dim method As MethodInfo = obj.GetType().GetMethod(methodName, BindingFlags.Instance Or BindingFlags.Public)
method.Invoke()
source
There is a function CallByName which does exactly that.
The function accepts 4 parameters:
object/class
function/procname
calltype (CallType.method, CallType.Get, CallType.Set)
(optional): parameter (in arrayformat)
The first parameter (object/class) can't be a string, so we have to cast your string to an object. The best way to do this is
Dim MyInstance As Object = Activator.CreateInstance(Type.GetType(which_mod))
So for your code:
Imports Microsoft.VisualBasic.CallType
Imports System.Reflection
Class Mod1
If x = 1 then
Mod2("Mod3","save_it")
else
Mod2("Mod4","edit_it")
end if
End Class
Module Mod2(which_mod, which_action)
' call the correct subroutine
Dim MyInstance As Object = Activator.CreateInstance(Type.GetType(which_mod))
CallByName(MyInstance , which_action, CallType.Method)
End Module

Outputting multiple variables defined in a method

I have series of basic calculations on a form triggered by the form load event:
Dim someVariableA As Integer
Dim someVariableB As Integer
Dim someVariableX As Integer = 1
Dim someVariableY As Integer = 2
someVariableA = someVariableX + someVariableY
someVariableB = someVariableX * someVariableY
I now require the exact calculations for a separate form. Rather than pasting the same again, is there a means by which I can place the calculation in a method that both forms can call upon?
Public Function someFunction()
' Above calculations placed here instead.
End Function
Private Sub someSub()
' Call calculations.
someFunction()
' ...now output and use variables from function.
TextBox1.Text = someVariableA
TextBox2.Text = someVariableB
End Sub
Ultimately, I'm expecting something that behaves like PHP's include function.
You are running into the issue of Scope. Where a variable is declared determines its availability. You probably know how to make variables visible to all methods in a form:
Public Class Form1
Private varA As String
Private var2 As Integer
These will be available to all methods in the form because the are declared at the Form level (unlike a variable declared (Dim) inside a procedure which will exist only locally). To make them visible to all methods in the app's forms, declare them in a module:
Public Module1
Friend varA As String
Friend var2 As Integer
Friend varX As DateTime
Declared in a module (1980s style!), they become global variables for your app. But there is good reason to avoid this. It is so easy to change a value, you can have methods which accidentally or unwittingly do so - remember they are now visible to everything even those procedure which might have no good reason to change them! Then, you spend time trying to locate those methods which are changing the value(s) but should not be.
A gigantic benefit of OOP is the ability to avoid this by using classes to hold the data and contain methods to manage that data - they can do everything from loading and saving to the calcualations you need. A sign that this might be what you need is that you have some variables you want to be global and already have methods which are global, combine them and you have a class:
Public Class Foo
Private varA As String
Private var2 As Integer
' some of these things might be better as Properties
' this allows the subscribers (users of the class) to change the
' values directly:
Public Property SomeDate As DateTime
Public Property Name As String
Public Property Value As Integer
Public Function GetSomething(aVar As Integer) As Integer
var2 += aVar ' update var2 for example
Return var2 ' return new value
End Function
To make the class available to all forms:
Public Module1
Friend myFoo As Foo ' makes it visible to all forms
Then create an instance of your class from your main form:
Public Class Form1
Private Sub Form_Load(....
myFoo = new Foo
Now, myFoo is an instance of the Foo class which not only houses those variables, but the methods to manage them:
Private Sub button_click(....
someVar = myFoo.DoSomething(42)

Declaring global, static variables

I'm trying to set a global variable in Visual Studio, but I can't make it static. Is there any way for me to set the variable as static and share it across different methods, or some way to save the variable each time it changes?
You have two options:
1 - Create a class that contains a Shared variable (this is the same as a static variable in C#)
Public Class GlobalVariables
Public Shared Bar As String
End Class
You can then access this using the class name:
GlobalVariables.Bar = "Hello world"
2 - Create a module (this is akin to a static class in C#)
Public Module GlobalVariables
Public Bar As String
End Module
You can then access this value in code like this:
Bar = "Goodbye cruel world"
If you use the number 1 option presented by #Matt Wilko, you can reference the shared member either through an object instance of the class or by referencing the class without an object reference. Both point to and increment the same variable and therefore reference the same value. Although, the Visual Studio compiler provides a warning about referencing an object instance and says that it will not be evaluated, it still compiles. The compiler's recommendation is to use the class name.
Public Class GlobalVariables
Public Shared Foo As Integer
End Class
Insert the following into a form and call IncrementIntegers() from a button click event procedure and you will find that myGlobalVariables.Foo and GlobalVariables.Foo both return 20.
Private Sub IncrementIntegers()
Dim myGlobalVariables As New GlobalVariables
myGlobalVariables.Foo = 0
GlobalVariables.Foo = 0
myGlobalVariables.Foo += 10
GlobalVariables.Foo += 10
Dim iLocalInt1 = myGlobalVariables.Foo
MessageBox.Show("myGlobalVariables.Foo = " & iLocalInt1.ToString)
Dim iLocalInt2 = GlobalVariables.Foo
MessageBox.Show("GlobalVariables.Foo = " & iLocalInt2.ToString)
End Sub
Note that with option 1, Foo must be qualified with either the class name or an object name. With option 2, it is a module and not a class so an object reference cannot be created. The public variable can be referenced without qualifying it with the module name unless a variable with the same name appears in another module in which case the compiler with throw a name conflict error. For example,
Public Module1
Public Foo As String
End Module
Public Module2
Public Foo As String
End Module
Remove Module2 and Foo can be called unqualified from anywhere.
Foo = "Happy birthday"
With Module2 present, Foo must be qualified with the name as both point to different variable and represent different and independent values.
Module1.Foo = "Goodbye cruel world"
Module2.Foo = "Hello new world"

Pointing to this object vba syntax

I have two class modules. Say class1 and class2. I want to set one of class2's properties to be class1 from within class 1. I know in java you can do something like
Class1{
Set Class2Object= This
}
Class2{
Declare Property as Class1
}
Does vba have an equivalent to "This" from java? Thanks!
in VBA you use Me instead of this
by the way in VBA you use Dim not Declare
and you don't have { and } you simply end it with End Classso your code should look like this
Public Class1
Set Class2.Propertyname = Me
End Class
Public Class2
Dim Propertyname as Class1
End Class
hope this helps

Extending a base class to a derived class

We have two classes BasicRace & AdvancedRace.
AdvancedRace inherits from BasicRace
I have a BasicRace but i want to 'convert' it to the advanced class.
See code below as a example:
Module Module1
Sub Main()
Dim bRace As New BasicRace With {.CourseID = 1, .MeetingDate = "2013-05-01", .RaceNumber = 1}
Dim aRace As New AdvancedRace
' Upgrade bRace to AdvancedRace???????
End Sub
End Module
Public Class BasicRace
Public Property MeetingDate As Date
Public Property CourseID As Integer
Public Property RaceNumber As Integer
End Class
Public Class AdvancedRace
Inherits BasicRace
Public Property RaceTitle As String
End Class
Any help would be great - I'm starting to think it can not be done unless i write a function to convert a basicRace to AdvancedRace going through each property one by one?
You can't "convert" from a base class to a subclass as such (you can't change the type of an existing object), but you can create new instance of the subclass that copies the properties from your base class.
Typical ways of implementing this for your classes might be:
a constructor in AdvancedRace that takes a BasicRace parameter and copies properties from it
a static method in AdvancedRace that takes a BasicRace parameter, creates the new object with copied properties, and then returns it
It's worth noting that this will result in two completely separate objects (one of each type) that aren't linked at all - changes in your AdvancedRace object won't be reflected in the BasicRace or vice-versa.