Calling method directly without instance variable - vb.net

Is there a way to call directly a method without creating instance of specific class like it is in C# so apart from that way:
Dim myclass as New ClassX
myclass.MyMethod()
is there a way to use soemthing like:
New ClassX.MyMethod
i found this way and seems to be working but not sure if its correct:
(New ClassX).MyMethod

If your method is an instance-level method you can only access it by using an instance of the class. By using
(New ClassX).MyMethod
you implicitly create a new instance that you access only once.
An alternative is to change the method's signature and mark it as a Shared method:
Public Class ClassX
Public Shared Sub MyMethod()
' ...
End Sub
End Class
Shared is the VB.NET way of creating a static method as it is called in C#. This way, you can access the method by only specifying the class name without creating an instance:
ClassX.MyMethod()

Related

groovy method scope when using a method reference

I have a groovy class that looks up a method reference and then invokes it. The method being invoked is a private method. When the actual class is an instance of the child class, it throws an error that it cannot find the private method, even though it is the public method in the parent that actually calls it.
In this case, I could obviously just call pMethod2() directly and that works, but I'm trying to understand why this doesn't work as written and if there's a way to correct it so it works.
class Parent {
def pMethod1() {
def m = this.&pMethod2
m() // this call fails if the calling class is of type Child
}
private def pMethod2() {}
public static void main(String[] args) {
new Child().pMethod1();
}
}
class Child extends Parent {}
It is a bit confusing, especially if you're used to C / C++. What you get when using the ".&" operator in Groovy is not an address, but an instance of MethodClosure.
The MethodClosure object contains an owner and a delegate object, which is used when resolving the method to call. In your example, the owner and delegate object will be "this", which is an instance of Child. The method to call is simply stored as a string.
So, the assignment
m = this.&pMethod2
is just a shorthand way of writing
m = new MethodClosure(this, "pMethod2")
When you invoke the m() closure, it will try to resolve (at runtime) the method by looking for methods named "pMethod2" in the owner and the delegate objects respectively. Since the owner and delegate is an instance of Child, it will not find private methods located in Parent.
To make your example work you must make sure that the method is visible to the owner and/or delegate of the closure.
This can be done several ways, for instance by changing the access modifier of pMethod2 to protected, or by creating the closure with an instance of Parent; something like this:
m = new Parent().&pMethod2
Note that is is irrelevant that you created the MethodClosure instance in a method where pMethod2 is actually visible. It is also irrelevant that you invoke the closure in a method where it is visible. The method is not visible to the owner or delegate of the MethodClosure, which is what is being used when resolving the method.

Accessing the same instance of a class in another form

I'm sure this is a simple question, but I don't have enough experience to know the answer. :)
DataClass, Form1, Form2
I have a public class, DataClass, in a separate file, DataClass.vb. In DataClass I have data stored in several arrays that I need to access. I have methods in DataClass so that I can access the data. One of them is GetName. Everything works fine on Form1. I need to access the same data in the arrays on a another form, but I am required to call a new instance of the class, so when I call the methods to access the arrays, the data is empty.
I've seen some threads mention creating a singleton class, but most are about C# which I am not as familiar with.
What is the best practice?
There are many ways in which you can do this.
One of them would involve creating a Module and then making the variable that instantiates your class Public inside the module:
Module MyGlobalVariables
Public MyDataClass As DataClass
End Module
Now, all the forms in your project will be able to access the DataClass via MyGlobalVariables.MyDataClass.
A preferable method would be to add a property to your Form2 that can be set to the DataClass instance:
Public Property MyDataClass As DataClass
Then, you would instantiate your Form2 as follows (assuming the variable you use to instantiate DataClass in Form1 is called _dataClass):
Dim frm2 As New Form2()
frm2.MyDataClass = _dataClass
frm2.Show()
And finally, another way would be to override the constructor of Form2 and allow it to receive a parameter of type DataClass. Then, you could instantiate Form2 as:
Dim frm2 As New Form2(_dataClass)
Hope this helps...
You can create a singleton class like this
Public Class DataClass
Public Shared ReadOnly Instance As New DataClass()
Private Sub New()
End Sub
' Other members here
End Class
You can access a single instance through the shared Instance member which is initialized automatically. The constructor New is private in order to forbid creating a new instance from outside of the class.
You can access the singleton like this
Dim data = DataClass.Instance
But this is not possible
Dim data = new DataClass() 'NOT POSSIBLE!
Since the singleton class is accessed through the class name, you can access it from the two forms easily.

MyBase can not to be used in a Extension Method?

I created a module to add some Extension Methods to a Class.
This Class inherits from another parent Class.
In the code of my Extension Methods, I would like to refer to the base Class using MyBase.
This doesn't seems to be allowed (Error message : "'MyBase' is not valid within a Module.")
<Extension()>
Public Function Get_OutOfSpace(val as ClassA) As Boolean
Return MyBase.IsOutOfSpace()
End Function
How can I invoke a method of my base class within an Extension Method?
That's why they force you to write extension methods in a module, so you can't make the mistake of using MyBase. But there's at least one other thing wrong with your code, you didn't extend anything. The first argument of an extension method must be a reference to the object, of the type you want to extend:
<Extension()>
Public Function Get_OutOfSpace(ByVal obj As Foo) As Boolean
''...
End Function
So a likely implementation is Return obj.IsOutOfSpace. Which in turn makes it very likely that you don't actually have any use at all for this extension method since the class you want to extend already has an IsOutOfSpace property.
Only use extension methods to add methods to classes. And only do so if you can't change the class.

Factory method for generics in VB.NET

I want to create a factory for generic classes in VB.NET and I am running into issues.
What I have are two interfaces:
IPersistentObject and IPManagerBase(Of T as IPersistentObject)
The logic is that for each type of peristent object I have a corresponding manager class handling query logic.
Now I have a base class like this:
public class PManagerBase(Of T as IPersistentObject) Implements IPManagerBase(of T)
So, now in the real world I have a persistent type "PUser" and a corresponding manager declared like this:
public class PUserManager implements PManagerBase(Of PUser)
I have about 100 of those persistent objects and corresponding manager classes.
Now I want to have a factory, which I would invoke like this (removing the details):
MyFactory.CreateManager<PUserManager>()
I am creating my Factory like this
public class MyFactory
public shared function CreateManager(Of T as {PManagerBase(Of IPersistentObject), New}) as T
return new T()
end function
end class
Looks great.
Now I want to invoke it:
Dim myManager = MyFactory.CreateManager<PUserManager>()
What happens?
I get a compile error: "PUserManager does not implement/inherit PManagerBase(Of IPersistentObject)". I get the message in German so this is a free tranlation.
What would I need to change to make this running?
It works if I declare my factory like this:
public class MyFactory
public shared function CreateManager(Of T as {PManagerBase(Of PUser), New}) as T
return new T()
end function
end class
But then the benefit is gone, since it works only for Managers of the PUser object.
A better solution is
public class MyFactory
public shared function CreateManager(Of T as {PManagerBase(Of U), New}, U as IPersistentObject) as T
return new T()
end function
end class
This works, but I have to call my factory method like this now:
Dim myManager = MyFactory.CreateManager<PUserManager, PUser>()
I don't like this since this is redundant and I don't need U at all in the function. In it's declaration PUserManager is tied to PUser.
Is there a better way? Why is PUserManager not inheriting from PManagerBase(Of IPersistentObject)?
This is a problem with generics, if you are using VS 2010 you may want to take a look at covariance and contravariance and modify your IPManagerBase definition accordingly.

How to load a class into the current instance within Sub New

Long term lurker, first time poster here.
I have written a class to model an object in vb.net, using vs2008 and framework 2.0. I am serializing the class to an XML file for persistent storage. I do this with a method in the class like this:
Public Sub SaveAs(ByVal filename As String)
Dim writer As New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file As New System.IO.StreamWriter(filename)
writer.Serialize(file, Me)
file.Close()
End Sub
I now want to do a similar thing but reading the class from file to the current instance, like this:
Public Sub New(ByVal filename As String)
Dim reader = New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file = New System.IO.StreamReader(FullPath)
Me = CType(reader.Deserialize(file), MyNamespace.MyClass)
End Sub
However, I cannot assign anything to “Me”. I’ve tried creating a temporary object to hold the file contents then copying each property and field over to the current instance. I iterated over the properties (using Reflection), but this soon gets messy, dealing with ReadOnly collection properties, for example. If I just copy each property manually I will have to remember to modify the procedure whenever I add a property in the future, so that sounds like a recipe for disaster.
I know that I could just use a separate function outside the class but many built-in .NET classes can instantiate themselves from file e.g. Dim bmp As New Bitmap(filename As String) and this seems very intuitive to me.
So can anyone suggest how to load a class into the current instance in the Sub New procedure? Many thanks in advance for any advice.
I'd put a shared load function on the class, that returned the newly de-serialised object.
e.g.
Public Class MyClass
...
Public shared Function Load(ByVal filename As String) as MyClass
Dim reader = New Xml.Serialization.XmlSerializer(GetType(MyNamespace.MyClass))
Dim file = New System.IO.StreamReader(FullPath)
Return CType(reader.Deserialize(file), MyNamespace.MyClass)
End Sub
End Class
...
Dim mine as MyClass = MyClass.Load("MyObject.Xml");
Hope this helps
Alternatively,
Encapsulate the data of your class in an inner, private class.
The properties on your outer visible class delegate to the inner class.
Then Serialising and De-serialising happens on the inner class, you can then have a ctor that takes the file name, de-serialises the inner hidden object, and assigns it to the classes data store.
The "New" method in VB.Net is a constructor for the class. You can't call it for an existing instance, as the whole purpose of the method is to create new instances; it's just not how the language works. Try naming the method something like "ReadFrom" or "LoadFrom" instead.
Additionally, given those methods, I would try to implement them using a Factory Pattern. The ReadFrom method would be marked Shared and return the new instance. I would also make the method more generic. My main ReadFrom() method would accept an open textreader or xmlreader or even just a stream, rather than a file name. I would then have overloads that converts a file name into a stream for reading and calls the main method.
Of course, that assumes I use that pattern in the first place. .Net already has great support for xml serialization built into the platform. Look into the System.Xml.Serialization.XmlSerializer class and associated features.