Using LuaInterface with VB.net - vb.net

I'm trying to wire up Lua to my VB.net game I am making. Now, I've read enough to know that I can wire each function up by itself like seen here:
pLuaVM.RegisterFunction("quit", pPrg.GetType(), pPrgType.GetMethod("quit"))
Now, how would I make it possible for my Lua scripters to instance classes, change properties of those classes, etc.
RegisterFunction just seems sloppy and not enough.
Thanks for any help!

My first piece of advise is to not use LUAInterface; as it isn't cross platform, and to instead use IronPython, which is just as easy to pick up as LUA, and will run on Windows and OSX, depending on how you are writing your game; XNA and OpenTK should work cross platform under mono for the graphics engine.
i found this out myself when experementing with LUA for my own vb.net based game, and eventually decided on iron python.
But assuming you want to stick with LUA; here is something you can try.
Based on the fact that you know:
Any vb.net code written cannot be changed after run time, you can do something like this:
Public Shared Lua as New LuaInterface
Sub Game()
Dim LuaCaller as New LuaAccess
Lua("LuaAccess") = LuaCaller
End Sub
Public Class LuaAccess
Public Sub Grant(NewClass as String, Variable as String)
Select Case NewClass
Case "LuaAccess"
Lua(Variable) = New LuaAccess
End Sub
End Class
Then from Lua:
LuaAccess:Grant("LuaAccess", "MyNewLuaAccess")
You can add a new case for each class you want lua to be able to create an instance of; and use that to create new instances of classes.
if you want it to be able to modify an active class used by the main program, just make the subs, or variables, or both in the class shared
Public Shared MyVar as Integer
That way there is only one copy of the variable, which any part of the application (even Lua) can modify.
Although I'll be honest IronPython really is more suited to this kind of thing, and is still being actively developed, unlike LuaInterface.
remember one thing; when it comes to scripting, you really don't want to give the scripting engine too much control; when it comes to games specifically you're giving them access to everything your engine can do; and that can be used to cheat if you are not careful.
good luck, and i hope i helped.
Based on LuaInterface runtime v2.0.50727
(the one that uses Lua51.dll)

Related

Unit Testing concrete classes

I have inherited a project that has no interfaces or abstract classes i.e. concrete classes only and I want to introduce unit testing. The classes contain lots of functions, which contain business logic and data logic; breaking every rule of SOLID (http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29).
I had a thought. I was thinking about creating interfaces for each of the poorly designed classes, exposing all functions. Then at least I can Mock the classes.
I am relatively new to Unit Testing (I have experience with a project, which was very well developed using interfaces in the right places). Is it a good idea to do this i.e. create interfaces for all the concrete classes (exposing all the functions and sub routines), just for unit testing?
I have spent some time researching this but I have not found an answer.
If your project has no tests at all, before adding any unit tests I'd much rather create higher level tests (i.e acceptance, functional and/or integration tests).
When you have those tests in place you know that the system is behaving as it should and also that it has certain level of 'external' quality (meaning by this that the inputs and outputs of your program are the expected ones).
Once your high level tests are working, you could try to add unit tests to the classes that already exist.
I bet that you will find yourself in the need to refactor some of the existing classes if you want to be able to unit test them so you can use your high level tests as a safety net that will tell you if you've broken anything.
This is a tough thing to tackle. I think you are on the right track. You'll end up with some ugly code (such as creating header interfaces for each monolithic class), but that should just be an intermediate step.
I'd suggest investing in a copy of Working Effectively with Legacy Code. First you could start by reading this distillation.
In addition to Karl's options (which let you mock via interception), you could also use Microsoft Fakes & Stubs. But these tools will not encourage you to refactor the code to adhere to SOLID principles.
Yes, that is a good start, however, having interfaces is less of a priority than having dependencies injected. If all of your legacy classes gain interfaces, but hidden internally they are still all interdependent, the classes will still be no easier to test. For instance, let's say you had two classes that looked like this:
Public Class LegacyDataAccess
Public Function GetAllSales() As List(Of SaleDto)
' Do work with takes a long time to run against real DB
End Function
End Class
Public Class LegacyBusiness
Public Function GetTotalSales() As Integer
Dim dataAccess As New LegacyDataAccess()
Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
I know what you're already saying... "I wish the legacy code was at least layered that well", but lets use that as an example of some legacy code which would be hard to test. The reason it's hard to test is because the code reaches out to the database and executes a time-consuming query on the database and then calculates the results from that. So, in order to test it in its current state, you would need to first write out a bunch of test data to the database, then run the code to see if it returns the correct results based on that inserted data. Having to write a test like that is problematic because:
It is a pain to write the code to setup the test
The test will be brittle because it depends on the outside database working properly and on it containing all the correct supporting data
The test will take too long to run
As you correctly observe, interfaces are very important to unit testing. So, as you recommend, lets add interfaces to see if it makes it any easier to test:
Public Interface ILegacyDataAccess
Function GetAllSales() As List(Of SaleDto)
End Interface
Public Interface ILegacyBusiness
Function GetTotalSales() As Integer
End Interface
Public Class LegacyDataAccess
Implements ILegacyDataAccess
Public Function GetAllSales() As List(Of SaleDto) _
Implements ILegacyDataAccess.GetAllSales
' Do work with takes a long time to run against real DB
End Function
End Class
Public Class LegacyBusiness
Implements ILegacyBusiness
Public Function GetTotalSales() As Integer _
Implements ILegacyBusiness.GetTotalSales
Dim dataAccess As New LegacyDataAccess()
Dim sales As List(Of SaleDto) = dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
So now we have the interfaces, but really, how does that make it any easier to test? Now we can easily create a mock data access object, which implements the same interface, but that's not really the core problem. The problem is, how do we get the business object to use that mock data access object instead of the real one? To do that, you need to take your refactoring to the next level by introducing dependency-injection. The real culprit is the New keyword in the following line of the business class:
Dim dataAccess As New LegacyDataAccess()
The business class clearly depends on the data access class, but currently it is hiding that fact. It's lying about it's dependencies. It's saying, come-on, it's easy, just call this method and I'll return the result--that's all it takes. When really, it takes a lot more than that. Now, let's say we stopped it from lying about it's dependencies and made it so it unabashedly stated them, like this:
Public Class LegacyBusiness
Implements ILegacyBusiness
Public Sub New(dataAccess As ILegacyDataAccess)
_dataAccess = dataAccess
End Sub
Private _dataAccess As ILegacyDataAccess
Public Function GetTotalSales() As Integer _
Implements ILegacyBusiness.GetTotalSales
Dim sales As List(Of SaleDto) = _dataAccess.GetAllSales()
' Calculate total sales
End Function
End Class
Now, as you can see, this class is much easier to test. Not only can we easily create a mock data access object, but now we can easily inject the mock data access object into the business object. Now we can create a mock which quickly and easily returns exactly the data we want it to return and then see if the business class returns the correct calculation--no database involved.
Unfortunately, while adding interfaces to existing classes is a breeze, refactoring them to use dependency-injection typically requires a lot more work. You will likely need to plan out which classes make the most sense to tackle first. You may need to create some intermediary old-school wrappers which work the way the code used to, so you don't break existing code while you are in the process of refactoring the code. It's not a quick and easy thing, but if you are patient and in it for the long-haul, it is possible to do it, and you will be glad you did.
I would recommend you go the interface route, but if you want to pay for a solution, then try one of these:
TypeMock
JustMock
Creating interfaces to test the classes is not a bad idea - the goal of unit testing is to exercise if the functions on a class are functioning as expected. Depending on the classes you are working with, this could be easier said than done - if there are a lot of dependencies on global states, etc. you will need to mock accordingly.
Given how valuable unit tests are, putting a bit of work into them (to a limit) will benefit you and developers you work with.
I prefer to create interfaces and classes as you need to test things and not all upfront.
Besides interfaces, you can use some techniques to test legacy code. The one I often use is "Extract And Override", where you extract some piece off "untestable" code inside other method and make it overridable. Them derive the class that you want to test and override the "untestable" method with some sensing code.
Using a mock framework will be as easy as adding keyword Overridable to the method and sets the returning using the mock framework.
You can find many techniques on the book "Working Effectively with Legacy Code".
One thing about existing code, is that sometimes it is better to write integration tests than unit tests. And after you have the behavior under test, you create unit tests.
Another tip is to start with modules/class that have less dependencies, that way, you become familiar with the code with less pain.
Let me know if you need an example about "extract and override" ;)

VB.NET: Avoiding redundancies

Each of my VB.NET projects needs a certain set of custom modules.
For example:
modLog
modGUID
modControls
modRegistry
In SOME of these modules I have a few references to other modules.
For example the sub modLog.WriteLog goes like this:
Public Sub WriteLog(Byval uText As String)
If globalclassOEM.IsOEMVersion Then
sPath = (some custom path)
Else
sPath = (some default path)
End if
'Write log text to file
End Sub
This is really stupid because sometimes I have to add really many modules and classes to a tiny projects just to solve some dependencies as the above and to be able to use a few modules that I really need.
Is there any best tactics in VB.NET to avoid such situations?
The best way to avoid such problems, would be to avoid that problem ;) Means: Libraries should do exactly what they are meant to do and not do some "extra work" in the backgorund. In your example: Why does the WriteLog function need to determine the path and why doesnt the caller define it and pass it to the logging function/class?
IF you still want or need to have the functions in that way, you might circumvent the problem by defining interfaces and then put ALL your interfaces into a single library, but NOT the classes that implement them. That would still require to load the file with the interface definitions, but of course you don't need to load any class that implements it.
You might also use some kind of plugin system and when your logging class (in this example) is created, it might try to dynamically load the required assemblies. If they do not exit, the class will without them, otherwise it can use them as pretended. Doesnt make programmers life easier, though (imho).
The "best" way (imho again) would be the first suggestion. Dont have "low level" libraries referencing other libraries. Everything else most likely would be considered to be a design flaw and not a "solution".
I have not covered a whole heap of referencing in VB.net, however, would it be possible for you to create a .dll with all the base modules. This would mean you could reference this .dll saving you time. For the extenuating circumstances where you have references to other modules you could just manually write that module.
As others have alluded to, you never want to directly include the same code file in multiple projects. That is almost never a good idea and it always leads to messy code. If you have common code that you want to share between two different projects, then you need to create a third project (a class library) which will contain the common code, and then the other two projects will just reference to the class library. It's best if you can have all three projects in the same solution and then you can use project references. However, if you can't do that, you can still have a direct file reference to the DLL that is output by that class library project.
Secondly, if you really want to avoid spaghetti code, you should seriously look into dependency-injection (DI). The reason I, and others have suggested this, is because, even if you move the common code into class libraries so that it can be shared by multiple projects, you'll still have the problem that your class libraries act as "black-boxes" that magically figure out everything for you and act appropriately in every situation. On the face of it, that sounds like a good thing for which a developer should strive, but in reality, that leads to bad code in the long run.
For instance, what happens when you want to use the same logging class library in 100 different projects and they all need to do logging in slightly different ways. Now, your class library has to magically detect all of those different situations and handle them all. For instance, some projects may need to save the log to a different file name. Some may need to store the log to the Windows event log or a database. Some may need to automatically email a notification when an error is logged. Etc. As you can imagine, as the projects increase and the requirements grow, the logging class library will need to get more and more complex and confusing which will inevitably lead to more bugs.
DI, on the other hand, solves all these issues, and if you adhere to the methodology, it will essentially force you to write reusable code. In simple terms, it just means that all the dependencies of a class should be injected (passed by parameter) into it. In other words, if the Logger class needs an event log, or a database connection, it should not create or reach out and find those things itself. Instead, it should simply require that those dependencies be passed into it (often in the constructor). Your example using DI might look something like this:
Public Interface ILogFilePathFinder
Function GetPath() As String
End Interface
Public Class LogFilePathFinder
Implements ILogFilePathFinder
Public Sub New(isOemVersion As Boolean)
_isOemVersion = isOemVersion
End Sub
Private _isOemVersion As Boolean
Function GetPath() As String Implements ILogFilePathFinder.GetPath
If _isOemVersion Then
Return "C:\TestOem.log"
Else
Return "C:\Test.log"
End If
End Function
End Class
Public Interface ILogger
Sub WriteLog(ByVal text As String)
End Interface
Public Class FileLogger
Implements ILogger
Public Sub New(pathFinder As ILogFilePathFinder)
_pathFinder = pathFinder
End Sub
_pathFinder As ILogFilePathFinder
Public Sub WriteLog(text As String) Implements ILogger.WriteLog
Dim path As String = _pathFinder.GetPath()
' Write text to file ...
End Sub
End Class
As you can see, it requires a little bit of extra work, but when you design your code like this, you'll never regret it. You'll notice that the logger class requests a path finder as a dependency. The path finder, in turn, requests an OEM setting as a dependency. So, to use it, you would need to do something like this:
Dim pathFinder As ILogFilePathFinder = New FileLogPathFinder(_OemSettings.IsOemVersion) ' Note, don't use a global to store the settings, always ask for them to be injected
Dim logger As ILogger = New FileLogger(pathFinder)
logger.WriteLog("test")
Now, you can easily reuse all of this code in any situation. For instance, if you have different projects that need to use a different log file path, they can still use the common FileLogger class, they just need to each implement their own version of ILogFilePathFinder and then inject that custom path finder into the common FileLogger. Hopefully you see how doing it this way can be very useful and flexible.

Declare global variables in Visual Studio 2010 and VB.NET

How do I declare a global variable in Visual Basic?
These variables need to be accessible from all the Visual Basic forms. I know how to declare a public variable for a specific form, but how do I do this for all the forms in my project?
There is no way to declare global variables as you're probably imagining them in VB.NET.
What you can do (as some of the other answers have suggested) is declare everything that you want to treat as a global variable as static variables instead within one particular class:
Public Class GlobalVariables
Public Shared UserName As String = "Tim Johnson"
Public Shared UserAge As Integer = 39
End Class
However, you'll need to fully-qualify all references to those variables anywhere you want to use them in your code. In this sense, they are not the type of global variables with which you may be familiar from other languages, because they are still associated with some particular class.
For example, if you want to display a message box in your form's code with the user's name, you'll have to do something like this:
Public Class Form1: Inherits Form
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
MessageBox.Show("Hello, " & GlobalVariables.UserName)
End Sub
End Class
You can't simply access the variable by typing UserName outside of the class in which it is defined—you must also specify the name of the class in which it is defined.
If the practice of fully-qualifying your variables horrifies or upsets you for whatever reason, you can always import the class that contains your global variable declarations (here, GlobalVariables) at the top of each code file (or even at the project level, in the project's Properties window). Then, you could simply reference the variables by their name.
Imports GlobalVariables
Note that this is exactly the same thing that the compiler is doing for you behind-the-scenes when you declare your global variables in a Module, rather than a Class. In VB.NET, which offers modules for backward-compatibility purposes with previous versions of VB, a Module is simply a sealed static class (or, in VB.NET terms, Shared NotInheritable Class). The IDE allows you to call members from modules without fully-qualifying or importing a reference to them. Even if you decide to go this route, it's worth understanding what is happening behind the scenes in an object-oriented language like VB.NET. I think that as a programmer, it's important to understand what's going on and what exactly your tools are doing for you, even if you decide to use them. And for what it's worth, I do not recommend this as a "best practice" because I feel that it tends towards obscurity and clean object-oriented code/design. It's much more likely that a C# programmer will understand your code if it's written as shown above than if you cram it into a module and let the compiler handle everything.
Note that like at least one other answer has alluded to, VB.NET is a fully object-oriented language. That means, among other things, that everything is an object. Even "global" variables have to be defined within an instance of a class because they are objects as well. Any time you feel the need to use global variables in an object-oriented language, that a sign you need to rethink your design. If you're just making the switch to object-oriented programming, it's more than worth your while to stop and learn some of the basic patterns before entrenching yourself any further into writing code.
Pretty much the same way that you always have, with "Modules" instead of classes and just use "Public" instead of the old "Global" keyword:
Public Module Module1
Public Foo As Integer
End Module
Okay. I finally found what actually works to answer the question that seems to be asked;
"When needing many modules and forms, how can I declare a variable to be public to all of them such that they each reference the same variable?"
Amazingly to me, I spent considerable time searching the web for that seemingly simple question, finding nothing but vagueness that left me still getting errors.
But thanks to Cody Gray's link to an example, I was able to discern a proper answer;
Situation;
You have multiple Modules and/or Forms and want to reference a particular variable from each or all.
"A" way that works;
On one module place the following code (wherein "DefineGlobals" is an arbitrarily chosen name);
Public Module DefineGlobals
Public Parts As Integer 'Assembled-particle count
Public FirstPrtAff As Long 'Addr into Link List
End Module
And then in each Module/Form in need of addressing that variable "Parts", place the following code (as an example of the "InitForm2" form);
Public Class InitForm2
Private Sub InitForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Parts = Parts + 3
End Sub
End Class
And perhaps another Form;
Public Class FormX
Sub CreateAff()
Parts = 1000
End Sub
End Class
That type of coding seems to have worked on my VB2008 Express and seems to be all needed at the moment (void of any unknown files being loaded in the background) even though I have found no end to the "Oh btw..." surprise details. And I'm certain a greater degree of standardization would be preferred, but the first task is simply to get something working at all, with or without standards.
Nothing beats exact and well worded, explicit examples.
Thanks again, Cody
Make it static (shared in VB).
Public Class Form1
Public Shared SomeValue As Integer = 5
End Class
Public variables are a code smell - try to redesign your application so these are not needed. Most of the reasoning here and here are as applicable to VB.NET.
The simplest way to have global variables in VB.NET is to create public static variables on a class (declare a variable as Public Shared).
A global variable could be accessible in all your forms in your project if you use the keyword public shared if it is in a class. It will also work if you use the keyword "public" if it is under a Module, but it is not the best practice for many reasons.
(... Yes, I somewhat repeating what "Cody Gray" and "RBarryYoung" said.)
One of the problems is when you have two threads that call the same global variable at the same time. You will have some surprises. You might have unexpected reactions if you don't know their limitations. Take a look at the post Global Variables in Visual Basic .NET and download the sample project!
small remark: I am using modules in webbased application (asp.net).
I need to remember that everything I store in the variables on the module are seen by everyone in the application, read website. Not only in my session.
If i try to add up a calculation in my session I need to make an array to filter the numbers for my session and for others.
Modules is a great way to work but need concentration on how to use it.
To help against mistakes: classes are send to the
CarbageCollector
when the page is finished. My modules stay alive (as long as the application is not ended or restarted) and I can reuse the data in it.
I use this to save data that sometimes is lost because of the sessionhandling by IIS.
IIS Form auth
and
IIS_session
are not in sync, and with my module I pull back data that went over de cliff.
All of above can be avoided by simply declaring a friend value for runtime on the starting form.
Public Class Form1
Friend sharevalue as string = "Boo"
Then access this variable from all forms simply using Form1.sharevalue
You could just add a new Variable under the properties of your project
Each time you want to get that variable you just have to use
My.Settings.(Name of variable)
That'll work for the entire Project in all forms
The various answers in this blog seem to be defined by SE's who promote strict adherence to the usual rules of object-oriented programming (use a Public Class with public shared (aka static), and fully-qualified class references, or SE's who promote using the backward-compatibility feature (Module) for which the compiler obviously needs to do the same thing to make it work.
As a SE with 30+ years of experience, I would propose the following guidelines:
If you are writing all new code (not attempting to convert a legacy app) that you avoid using these forms altogether except in the rare instance that you really DO need to have a static variable because they can cause terrible consequences (and really hard-to-find bugs). (Multithread and multiprocessing code requires semaphores around static variables...)
If you are modifying a small application that already has a few global variables, then formulate them so they are not obscured by Modules, that is, use the standard rules of object-oriented programming to re-create them as public static and access them by full qualification so others can figure out what is going on.
If you have a huge legacy application with dozens or hundreds of global variables, by all means, use Modules to define them. There is no reason to waste time when getting the application working, because you are probably already behind the 8-ball in time spent on Properties, etc.
The first guy with a public class makes a lot more sense. The original guy has multiple forms and if global variables are needed then the global class will be better. Think of someone coding behind him and needs to use a global variable in a class you have IntelliSense, it will also make coding a modification 6 months later a lot easier.
Also if I have a brain fart and use like in an example parts on a module level then want my global parts I can do something like
Dim Parts as Integer
parts = 3
GlobalVariables.parts += Parts '< Not recommended but it works
At least that's why I would go the class route.
You can pipe the variable in to a file in the output directory and then load that file in the variable.
Imports System.IO
This code writes the file.
Dim somevariable = "an example"
Dim fs As FileStream = File.Create("globalvars/myvar1.var")
Dim filedata As Byte() = New UTF8Encoding(True).GetBytes(somevariable)
fs.Write(filedata, 0, filedata.Length)
fs.Close()
This loads the file in another form.
Dim form2variable
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText("globalvars/myvar1.var")
form2variable = filereader
Public Class Form1
Public Shared SomeValue As Integer = 5
End Class
The answer:
MessageBox.Show("this is the number"&GlobalVariables.SomeValue)

Internationalization in VB.Net : Choosing the right structure type

I'm about to start translating my vb.net application, and I don't want to use the default methods provided by Visual Studio to do so. I need my application to be very light, and it nearly doubles it size to use the resources option.
Therefore, I'm planning to use some thing like a class, of which I would have one instance per language. Since I don't want to distribute language files as separate files (I'd rather have them hard-coded), I would like to find an easy way to check if every field of the class is initialized. I was thinking of something like an Interface, where I would do something like this:
Public Interface Language
Dim HelloMsg As String
Dim GoodbyeMsg As String
End Interface
Public class English Implements Language
HelloMsg = "Hello!"
GoodbyeMsg = "Goodbye!"
End Class
It's obviously not the right way to do it (although I could use properties instead of vars), but I was wondering whether the was a way to have the compiler check that everything is translated and warn about it if not.
Anyway, maybe is there a much better way to handle this problem ?
Thanks a lot!
CFP.
I'm not convinced that you should dump the resource-based localization approach just because your app has grown in size. Indeed, it could've grown from 100 Kb to 200 Kb, but this is it! It won't grow this much more. And 200 Kb is nothing nowadays.
So my advice is to reconsider and go resource-based route.
I've decided to use a singleton class that loads a translation file, with a method that loops through all items on a form and translate on-the-fly. See Create Synchronicity source code for more details (more specifically TranslateControl in this code file)

Basic questions about Classes, Modules and interaction

I am new to vb.net and very frustrated.
Like all good programmers I want to split my code into separate files based on functionality . Some of my code interacts with users via Forms and some interacts with lab equipment behind the scenes (no direct user interaction). Sometimes a user will change something that will impact the lab equipment and sometimes something will happen with the lab equipment that a user needs to be aware of. When I use VS to create files I have to choose a Module or Form. VS then creates an empty file with a with either
Public Class Foo
End Class
or
Module Foo
End Module
If I have a bunch of files, each a Module, and if I define routines in a Module to be Friend then I can call them from other Modules, so:
Module Foo
Friend Sub DoSomeWork()
End Sub
End Module
Code in Fee can call routines in Foo -
Module Fee
Friend Sub Stuff()
DoSomeWork()
End SUb
End Module
When I create a Form, VS creates a Class. I find that I can call subroutines defined in a Module from a Class but when I try to call from a Module into a Class I get an error that the routine I am trying to call is not declared. I also cannot call from one Class into another Class. Declarations seem to apply only to library routines outside my program.
I have looked through several online explanations and tutorials, but frankly I don't understand these nor do I care about "inheriting from the base class" and all the other gobbledygook that such "explanations" contain. I want to concentrate on building my application.
My Main form has the name "Main"
I tried putting all the module code into the Main Class first by renaming "Module Foo" to "Public Partial Class Main" - bad idea - creates an impossible-to-find duplicate error. I tried creating empty code files, defining them as Public Partial Class Main and putting the Module code into them, - this worked in that code in the Class Main could call the "Module" code (which was now in Main) and vice-versa, but, other Forms (of course I have more than one) are created by VS to have their own Classes and once the "Module" code is moved out of Modules into Class Main the other Forms(Classes) could not call the code anymore.
I just want some recipe (best practice) I can follow to for defining Modules and Classes so that code and data can be shared.
ANSWER from below
To invoke a subroutine in another Class you simply need to put the class name in front of the subroutine name.
So not
DoSomeWork()
but
Foo.DoSOmeWork()
This may be obvious to all of you experienced programmers but not to me. You do not have to prepend a class/module name to a Module-to-Module call or a Class-to-Module call, only to calls that are made into Classes. Personally, for the sake of consistency, I think the things should be the same, but it would probably violate some OO rule. Anyway thank you to all.
Generally, if you have a function that needs to be called from more than one form, or from forms and modules, put it in the main module. If you have an exceptional case and need to call a function or sub in a form from another form or a module, you can declare it to be public:
Public Class Form1
public sub test(i as integer)
...
end sub
end class
and then you can call it by referring to the class.subname:
call form1.test(7)
NomD,
Like all good programmers
you should indeed care
about "inheriting from the base class" and all the other gobbledygook that such "explanations"
This will make you a better programmer and taking the time to understand why proper code structuring is important will also begin to yield better results for you.
I am not sure why two commentors seem to have an issue with VB.Net. The question would be the same regardless of the language, since both are C# and VB are built on .Net. Code can be written poorly in C#, just like VB. Please leave the language wars at home. NormD, the answer to your question should really be to direct you to the resources needed to better understand the problem. Here is an article on scope that might help a bit - class scope. The reason you are getting the behavior that you see is due to what you are working with. Modules (similar to static classes in C#) are created when you program begins, so there is no need to create them. So you can reference a method on a module, like so - module.method. Classes on the other hand, some exceptions, need to be created in order to be referenced. So to use an employee (or form class) you must create a variable of that class. So you would use dim myemp as New Employee() and then call myemp.method() from your module. This is a rather simplistic description, so please read the scope article and other MSDN articles for more information. I am sure other posters can post additional links with good information. Hope this helps a bit.
Wade
It seems like you don't understand the basics of object-oriented programming (OOP).
If you DON'T want to learn how to design your application in an object-oriented way, then only create modules in your application and you will be able to call functions from one to another without any problem. But this will result in code that will not be easily maintainable and scalable.
The other option is to learn OOP by picking a book about it, or following a course or tutorial on the subject. It's a significant investment but it will result in more robust code that will scale better when your application grows.