VB.net give module access to only specific class - vb.net

I have a VB net Class which will use very very large string constants...
I want to define these constants in a Module in a different file as to make the code easier to read and update.
I would like the Module to be Private to everything else except the Class that uses it.
Is this possible?
Thanks
Tony

Related

What to use in the absence of "include"

So, I'm writing a small program in VB.net and I was wandering if there's a replacement for the include statement I'm used to in C/C++? That's instead of making all my classes and functions "public shared".
Are their security concerns, or is it bad practice to keep declaring all the classes or functions I wish to use in other .vb files as public shared?
For example let's say I write a hashing function for passwords within passwords.vb and I want to use it within a UI file login.vb, to do this I would declare my hashing function as a public shared funtion within a public class (unless I'm missing another way). That way I can access it by using something along the lines of password.Hash(STRING) where password. is a reference to my password.vb file.
Now in C/C++ I would add an include statement to the header file that would define everything I needed it too. I know header files don't exist but there's not other way to include a separate .vb file, other than making everything public? It just seems odd to me and it feels like having possibly hundreds of public classes/variables/functions etc... is somehow the wrong way to do it?
I'm aware of .dll referencing as an alternative, but I don't really want to have 20 .dll files associated with a program if I can help it, or unless it should be like that?
Thanks for your help and I hope that what I'm asking makes sense.
Well you need to do some extra effort if you wish this separation.
Namespaces are not really enforced inside VB.net, but you could use them to arrange your code in such a way that you can use the Imports Namespace statement.
Lets say we have this dummy class, this would now be publicly accessible in your code without any extra effort
Module PasswordHandler
Public Function Hash(ByVal password As String) As String
Return password
End Function
End Module
However, you can change the namespace of the Module if you want to
Namespace Security
Module PasswordHandler
Public Function Hash(ByVal password As String) As String
Return password
End Function
End Module
End Namespace
And this would now "hide" the Module from your program, until you use the Imports ProgramName.Security statement on the top of your code, as the following:
Imports IncludeSampleVB.Security
Module Module1
Sub Main()
Dim salt As String = PasswordHandler.Hash("dummy")
End Sub
End Module
This way you could structure your code in a way that might seem more familiar to you :) Btw, for static functions, you can also simply use Modules, they don't have to be shared classes, as you could see here: Classes vs. Modules in VB.NET

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)

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.

Visual Studio - manage multiple files that are part of one Class - classes, modules

My VB project is large enough that it requires several files. It was originally developed as a Console App and I created each file as a MODULE. All modules could use subroutines, data structures and constants from other MODULES and everything worked fine. I needed to add basic windowing to the app and this required that the app be converted from a Console App to a Windows Forms App. The main window is Form1 which is not a MODULE but a CLASS. The problem is that some MODULE based functions cannot access subroutines, data and constants that are defined within the CLASS Form1 unless they are incorporated into the CLASS file and this makes the CLASS file very large. If I add a new Class file to the project, it also cannot interoperate with Class Form1 in the same way that multi-MODULE code interoperates.
How does one spread CLASS code across several files and still allow it to interoperate as if it were in a single file? Alternatively, how does one create several CLASS files that operate the way multiple MODULE files operate.
I am sure that there are all kinds of best practices that I am violating but the goal to to get some prototype software working and interfaced to some lab equipment.
Thank you in advance
Use a partial class (Partial keyword on the class declaration). Each partial "bit" of the class will be merged at compile time. All partial bits must be in the same project.
Modules are default shared and do not require initialization with the New keyword. When you made your console app a windows app, it became a class...You could change it to the same behavior as a module simply by making it a Public shared Class and making all properties and methods inside shared as well.
so while you can access your methods and properties in your modules without initialization, you would need to use the NEW method to initialize your Class methods.
To access the Class from the module you would simply have to use:
SomeModulemethod
dim x as new CLASS
CLASS.SOMEMETHOD
someModuleMethod End
You could also use Partial Classing to split up your Classes, but it is much better to decide if you really need a separate class for what you want to do.