Adding a global function - vb.net

I am trying to add a new global function
I am doing it like that:
Function MessageYNC() As String
{
return "dd";
}
End Function
Public Class SatelliteAPI
End Class
But i am getting error -> Statement is not valid in a namespace.
on the first line
Any idea what is wrong ?

The function belongs inside
the class.
The curly
braces and semicolons don't belong
in VB. Those are C#.
In
order for your method to be global,
you will need to declare it as
Shared. If your entire class
consists of nothing but shared
methods, you may consider creating a
module as opposed to a class.
Here's an explanation of the
difference between a class with
shared methods and a module.
Public Class SatelliteAPI
Public Shared Function MessageYNC() As String
Return "dd"
End Function
End Class 'SatelliteAPI
Public Class TestClass
Public Sub TestMessageMethod()
Console.WriteLine(SatelliteAPI.MessageYNC)
End Sub
End Class 'TestClass

Put the function into a class or module. If you put it into a class, you need to make it Shared. So it's either
Module MyFunctions
Function MessageYNC() As String
Return "dd"
End Function
End Module
or
Public Class SatelliteAPI
Shared Function MessageYNC() As String
Return "dd"
End Function
End Class
in which case you would access it as StaelliteAPI.MessageYNC.

Related

FluentValidation Custom Function within Validator Class

Using this example from the FluentValidation website, I'm converting the concept to VB.NET using my own classes. The part in interest to my issue is the Must(BeOver18), which calls the protected function. Note that this call doesn't pass a parameter to BeOver18:
public class PersonAgeValidator : AbstractValidator<Person> {
public PersonAgeValidator() {
RuleFor(x => x.DateOfBirth).Must(BeOver18);
}
protected bool BeOver18(DateTime date) {
//...
}
}
I created my own validator class in VB.NET like this, using the same principal as above but instead for a function called CustomerExists:
Public Class ContractValidator
Inherits AbstractValidator(Of ContractDTO)
Public Sub New()
RuleSet("OnCreate",
Sub()
RuleFor(Function(x) x.CustomerID).NotEmpty
' Compiler error here:
' BC30455 Argument not specified for parameter 'customerID'.....
RuleFor(Function(x) x.CustomerID).Must(CustomerExists)
End Sub
)
End Sub
Protected Function CustomerExists(customerID As Integer) As Boolean
Return CustomerService.Exists(customerID)
End Function
End Class
ISSUE: The line in VB.NET with .Must(CustomerExists) is giving the "Argument not specified for parameter 'customerID'..." compiler error. The C# example does not pass a parameter to BeOver18. I tried an additional anonymous in-line function to try to pass ContractDTO.CustomerID, but it doesn't work as it's not recognized:
' This won't work:
RuleFor(Function(x) x.CustomerID).Must(CustomerExists(Function(x) x.CustomerID))
I'm at a loss on how the C# example can call it's function without a parameter, but the VB.NET conversion cannot. This is where i need help.
Your CustomerExists function needs to be treated as a delegate. In order to do that, change the following:
Original
RuleFor(Function(x) x.CustomerID).Must(CustomerExists)
Update
RuleFor(Function(x) x.CustomerID).Must(AddressOf CustomerExists)

Is a Module really identical to a SharedMembers-NotInheritable-PrivateNew Class?

I can read a lot over the Internet that VB.Net Modules are the same thing as c#.Net Static Classes. I can also read that something close to a Static Class is a class which would look like this:
'NotInheritable so that no other class can be derived from it
Public NotInheritable Class MyAlmostStaticClass
'Private Creator so that it cannot be instantiated
Private Sub New()
End Sub
'Shared Members
Public Shared Function MyStaticFunction() as String
Return "Something"
End Function
End Class
I find this code heavy to draft, and to read. I would be much more confortable just using a Module like this:
Public Module MyEquivalentStaticClass
Public Function MyStaticFunction() as String
Return "Something"
End Function
End Module
However, with a Module you loose one level of Namespace hierarchy, and the following 3 statements are equal:
'Call through the Class Name is compulsory
Dim MyVar as String = Global.MyProject.MyAlmostStaticClass.MyStaticFunction()
'Call through the Module Name is OPTIONAL
Dim MyVar as String = Global.MyProject.MyEquivalentStaticClass.MyStaticFunction()
Dim MyVar as String = Global.MyProject.MyStaticFunction()
I find this very inconvenient and this either pollutes the Intelisense, or forces me to create additionnal levels of Namespace, which then means more Module declaration, i.e., more Intelisense pollution.
Is there a workaround or is this the price to pay if you want to avoid the heavy SharedMembers-NotInheritable-PrivateNew Class declaration?
Additionnal references include the very good post by Cody Gray: https://stackoverflow.com/a/39256196/10794555
No, there is no exact equivalent to a C# static class in VB.NET. It would be nice if VB had the ability to add the Shared modifier to a class declaration, like this:
Public Shared Class Test ' This won't work, so don't try it
' Compiler only allows shared members in here
End Class
But, unfortunately, it does not. If you do that, the compiler gives you the following error:
Classes cannot be declared 'Shared'
That leaves us with the two options you listed:
Either you make a non-instantiable class containing only Shared members (without the safety of that rule being enforced by the compiler), or
Use a Module, which makes everything Shared, even though you don't explicitly say so via the Shared modifier
As you said, many people don't like the loss of the class name being required, as a sort-of extra namespace layer, so they prefer the Class with only Shared members over the Module. But, that's a matter of preference.
It's worth noting that, while you don't have to specify the module name everywhere you call its members, you can always do so if you wish:
MyModule.MyMethod()
While a "SharedMembers-NotInheritable-PrivateNew Class", as you so eloquently called it, is the closest approximation to a static class, it's only functionally equivalent. If you use reflection, you'll see that the attributes of the type are not the same. For instance, in VB:
Module MyModule
Public Sub Main()
Dim t As Type = GetType(MyClass)
End Sub
End Module
Public NotInheritable Class MyClass
Private Sub New()
End Sub
Public Shared Sub MyMethod()
End Sub
End Class
If you take a look at t.Attributes, you'll see that it equals Public Or Sealed. So the MyClass type is both sealed (NotInheritable) and public. However, if you do this in C#:
class Program
{
static void Main(string[] args)
{
Type t = typeof(Test);
}
}
public static class MyClass
{
public static void MyMethod()
{ }
}
And you inspect the t.Attributes again, this time, the value is Public | Abstract | Sealed | BeforeFieldInit. That's not the same. Since you can't declare a class in VB as both NotInheritable and MustInherit at the same time, you have no chance of exactly duplicating that thing. So, while they more-or-less are equivalent, the attributes of the types are different. Now, just for fun, let's try this:
Module MyModule
Public Sub Main()
Dim t As Type = GetType(MyModule)
End Sub
End Module
Now, the t.Attributes for the module are Sealed. That's it. Just Sealed. So that's not the same either. The only way to get a true static class in VB (meaning, the type has the same attributes when inspected via reflection) is to write it in a C# class library, and then reference the library in VB.
I would be much more confortable just using a Module
So use a Module.
Module SomeModuleNameHere
Public Function MyStaticFunction() As String
Return "Something"
End Function
End Module
You don't need Global.MyProject or the Module name at all, just call your function directly, from anywhere:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim x As String = MyStaticFunction()
Debug.Print(x)
End Sub
But if you want to, you can use the Module name, without the Global part:
Dim x As String = SomeModuleNameHere.MyStaticFunctions
The only time you must use the Module name, however, is if you have two functions with the exact same name in different modules. Then you'd have to differentiate them by using their fully qualified names.
From all the discussions held so far, and thanks to the input by Steven Doggart and comments by TnTinMn, I have come to conclude with the following broad feedbacks and guidelines.
Nota: This post refers to 'Static' Classes, whilst the Static keyword is used for C#.Net, not VB.Net. The VB equivalent is Shared, but Shared Classes are not permited with VB (only the Members). The guidelines described below are tentatives to achieve in VB something close to a C# Static Class.
Since such VB Classes cannot be Shared, they are described as 'Static'.
Nota bis: In all the examples, I purposely added a layer of Namespace (consistently called "MySpace") so that there is no confusing as to in which Namespace layer the examples sit: they are all in the MySpace layer. The MySpace layer is not compulsory and can be stripped out depending on your needs.
In general
Use a Module but do not rely on the Module name as a Namespace layer. Rather, fully integrate the path in a Namespace declaration, such as:
Namespace MySpace.MyStaticClass
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Then the Static 'Members' should be accessed via Global.MyProject.MySpace.MyStaticClass.MyStaticFunction()
Nota: Part of the Namespace path can be stripped depending on where
you are located. Usually, MySpace.MyStaticClass.MyStaticFunction()
will be sufficient.
Nota bis: Using _Module as the Module name will
reduce the appereance of the Module in the Intelisense dropdown, and
yet make it crystal clear this is a Module.
When wishing to encaspulate Static Classes
Under such context the general above-mentionned style would produce:
Namespace MySpace.MyStaticClass
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Namespace MySpace.MyStaticClass.MyStaticSubClass1
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Namespace MySpace.MyStaticClass.MyStaticSubClass2
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
This can quickly be heavy in the sense that it requires a separate Namespace declaration for each 'encapsulated' 'Static Class'. Disadvantages include:
Heavy review because understanding the Namespace architecture/arborescence will be less intuitive: in the above example that would mean checking all the declaration which include 'MyStaticClass'.
Heavy drafting because of the additionnal Namespace declarations.
Heavy maintenance because changing a parent Namespace will require a change in several Namespace declarations: in the above example that would mean changing 'MyStaticClass' 3 times. (Right-Click/Rename is your best friend here)
An alternative is to use encapsulated Classes with Shared members:
Namespace MySpace
Public Class MyStaticClass
Public Function MyStaticFunction()
Return "Something"
End Function
Public Class MyStaticSubClass1
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public Class MyStaticSubClass2
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Class
End Namespace
Nota: As Steven Doggart pointed out in a separate post, people usually import Namespaces, but do not import Classes, so encapsulating Classes will usually "force" the reliance on the full path across encapsulated Classes : MyStaticClass.MyStaticSubClass1.
You cannot encapsulate a Module within another Module, but you could always use a mixture of a Module in which you encapsulate one or several Classes and Sub-Classes. The example below achieves something similar to the above example:
Namespace MyStaticClass
Public Module _Module
Public Function MyStaticFunction()
Return "Something"
End Function
Public Class MyStaticSubClass1
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public Class MyStaticSubClass2
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Module
End Namespace
When publishing a Class Library (DLL)
If your final product is a DLL you intend to share with a broader audience, it is recommended to put safety nets around your 'Static' Classes. Although this will not affect how the compiler will see your code, it will prevent someone else from making mistakes, or at least quickly trigger errors and assist debugging swiftly:
Make the Class NotInheritable, so that no one tries to derive a Class from a Static Class: it is typically useless to derive such Classes.
Make the New Creator statement Private, so that no one tries to instantiate the Class: the Static Class should not include any non-Static (Shared) members; if so, that is a typo and trying to instantiate the non-Shared Member will likely bring problems.
The example below achieves something similar to the above examples:
Namespace MySpace
Public NotInheritable Class MyStaticClass
Private Sub New()
End Sub
Public Function MyStaticFunction()
Return "Something"
End Function
Public NotInheritable Class MyStaticSubClass1
Private Sub New()
End Sub
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public NotInheritable Class MyStaticSubClass2
Private Sub New()
End Sub
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Class
End Namespace
When dealing with an Extension
A <System.Runtime.CompilerServices.Extension()> can only be declared within a Module block. However the Module Name has no impact on the Extension so this topic is not really relevant here.
See link provided by Peter Macej: https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/procedures/extension-methods

How do I refer to two different classes by one name in vb.net

I have two classes to handle database operations, one for MySQL (DBMySQL), and another for SQLite (DBSQLite). The user chooses which database system to use.
The functions within the classes have the same names, but are obviously slightly different to handle the variations in databases.
I would like to refer to the chosen class by one name throughout the application. I have set a global variable DB.
In a procedure I can: Dim DB as New DBMySQL (or DBSQLite). This works within the procedure, but not globally, but I can see all the functions when coding.
If I instead use: DB = New DBMySQL, this works globally, but no class functions are displayed when coding.
Any alternatives?
Use the concept of inheritance, and create a MustInherit class with MustOverride methods and/or properties.
Public MustInherit Class AbstractDB
Public MustOverride Function MyQuery(input As Object) As Object
Public MustOverride Sub MyUpdateMethod(input As Object)
End Class
Public Class DBMySQL
Inherits AbstractDB
Public Overrides Function MyQuery(input As Object) As Object
End Function
Public Overrides Sub MyUpdateMethod(input As Object)
End Sub
End Class
Public Class DBSQLite
Inherits AbstractDB
Public Overrides Function MyQuery(input As Object) As Object
End Function
Public Overrides Sub MyUpdateMethod(input As Object)
End Sub
End Class
Then, when you want to use your classes, make your DB global variable of type AbstractDB. You could then create either DBMySql or DBSQLite and assign it to your DB variable. The method names will all be the same, because they all inherit the same base class. But each derived class must fill out the content of those methods on its own.
Dim DB as AbstractDB = New DBMySQL
You could also use an interface.
Public Interface IRepository
' common functions of MySQL and SQLLiteclasses
End Interface
Public Class MySQLRepository
Implements IRepository
End Class
Public Class SQLLiteRepository
Implements IRepository
End Class
Public Function GetDB(userChoice As String) As IRepository
If userChoice = "MySQL" Then
Return New MySQLRepository()
Else
Return New SQLLiteRepository
End if
End Function
Dim DB As IRepository = GetDB(userChoice)
This is a basic implementation of the Repository pattern. The example in the link is in C#, but, as you're probably aware, it's not easy finding examples in VB. Fortunately, there are lots of C# to VB converters.
The abstract example Sean Skelly gave should also work. You may want to research the difference between abstract classes and interfaces.

Is this possible to set Attributes in an Class Extension?

Is this possible to use <Attributes> on a method in a Class extension ?
Here is a Class A
Public Class Goblin
Inherits Monster
Enum goblinsRole
Chief
Grount
End Enum
Public Property name As String
Public Property role As goblinsRole
Private healthPoints As Integer
Public Sub New(into As Integer)
healthPoints = into
End Sub
Public Sub hitBy(damage As Integer)
<...>
End Sub
<ValidationMethod()>
Public Function checkByTheWitchDoctor()
<...>
End Function
<ValidationMethod()>
Public Function isAlive()
<...>
End Function
End Class
Here is an extension of this class A
Module ModuleExtension
<ValidationMethod()>
<Extension()>
Public Sub PrintDateOfDeath(ByVal aGoblin As DomainModelFake.Goblin)
<...>
End Sub
<Extension()>
<ValidationMethod()>
Public Function smashedByAGrount(ByVal aGoblin As DomainModelFake.Goblin) As Boolean
<...>
End Function
End Module
When I use reflection to get the methods that are tagged with this attribute, I only get the list of methods that are located in the Class A definition without those that are located in the extension.
In extenso, it means that I only see :
checkByTheWitchDoctor()
isAlive()
but i do NOT see :
PrintDateOfDeath()
smashedByAGrount()
is this a normal behavior of reflection ? It doesn't search into the extensions ?
I am assuming that you try to find all methods of the Goblin class, and if that is the case, then yes, this is the normal behavior of reflection.
Extension methods are not a member of the type they are designed for. If you do Type.[GetType]("Goblin").GetMethods(), you will only get the methods defined there.
Extension methods are nothing but static (Shared in VB) methods that are decorated with a special attribute. So if you want to find those, you need to get the methods of ModuleExtension.
If you do not know the name of ModuleExtension at runtime, you could try looking for all static types in the assembly, and search those for static methods marked with an ExtensionAttribute and accepting a first parameter of type Goblin.

Can we declare a class in two files in vb.net

Say some function is defined in one file and another function is defined in another file
In C++ you can do that right
You have to create partial class. That way you may splits the definition of class into two or more files.
You can use Partial classes msdn link.
This means you can do something like this:
Partial Public Class partialClass
Public Sub method1()
End Sub
End Class
Partial Public Class partialClass
Public Sub method2()
End Sub
End Class
BTW, this is not the same you can do in C++. In C++, you can separate function declaration from the implementation. In VB, you can separate methods and properties, but you can't declare a function in one partial class and implement it in the another partial class