Get reference to main class from a property - vb.net

I have a class Class1 with several properties (Property1, Property2, ...)
For some design reasons, I have access only to, let's say, Property1.
Is there a way to get a reference to Class1 ?
I tried Property1.Parent, Property1.Base but both failed.
I'm using a heavy workaround which is creating a separate class for each property with a reference to the main class:
Public Class DerivedProperty1
Inherits Property1
Public ParentClass as Class1
Public Sub New(ParentClass as Class1)
me.ParentClass = ParentClass
End Sub
End Class
and then Class1 will become
Public Class Class1
Public DerivedProperty1 as DerivedProperty1
...
End Class
Is there another way different from this workaround ?
Thank you.

There is nothing build for that.
That's because the Class1.Property property really just hides a reference to a Property1Class class instance stored somewhere else. And because of that, the same Property1Class instance can be referenced by more then one Class1 instances.
And your naming in misleading. Property1Class class does not derive from Class1 class. It's just used by that class as a type of one of properties.
So if you need that kind of functionalty, you have to code it by yourself.

Related

Implement an interface in partial class

I need all my TableAdapters to implement a custom interface. The problem is that some of the members defined by the interface reside in the DataSet's designer file, which I don't want to (and shouldn't) alter, as that code will be regenerated automatically. I can't relocate those members to my code file either for the same reason. What's my way out of it?
When you implement an interface, the members you declare do not have to have the same names as the members of the interface and they don't have to be public. Let's say that you have this designer-generated class:
Partial Public Class SomeClass
Public Sub FirstMethod()
Console.WriteLine("FirstMethod")
End Sub
Public Sub SecondMethod()
Console.WriteLine("SecondMethod")
End Sub
End Class
and you want it to implement this interface:
Public Interface ISomeInterface
Sub FirstMethod()
Sub ThirdMethod()
End Interface
Notice that the interface has a method named FirstMethod but SomeClass already has a method named FirstMethod. You can add your own partial class to implement the interface like this:
Partial Public Class SomeClass
Implements ISomeInterface
Private Sub FirstMethodInternal() Implements ISomeInterface.FirstMethod
Me.FirstMethod()
End Sub
Public Sub ThirdMethod() Implements ISomeInterface.ThirdMethod
Console.WriteLine("ThirdMethod")
End Sub
End Class
The method that implements ISomeInterface.FirstMethod is not named FirstMethod so it doesn't clash with the existing method with that name and it is also Private so it cannot be accessed from outside using a reference of type SomeClass. Using a reference of type ISomeInterface is another matter though. If you use code like this:
Dim sc As ISomeInterface = New SomeClass
sc.FirstMethod()
sc.ThirdMethod()
you'll find that the FirstMethodInternal method of your SomeClass object gets invoked and, in turn, invokes the FirstMethod method of the same object. Try running that code and placing breakpoints on the FirstMethod and FirstMethodInternal methods to prove it to yourself.

How do I use a partial class as a subclass?

I am trying to implement a mySubClass.vb file as a nested subclass of another main class. It seems like the Partial Class idea is what I need but the implementation isn't working when I try to pull mySubClass.vb in as a nested subclass of another main class.
My original implementation of this code used mySubClass directly so I know the functionality works. I just want to use mySubClass as a data structure within clsMain.
Main Class
Public Class clsMain
Public Property myIntProp as Integer
Public property myStrProp as String
'other properties
Partial Public Class MySubClass
'I want this functionality to be accessible via clsMain.MySubClass
'Just like any other property or function of clsMain
'Partial would keep things organized nicely
End Class
End Class
Sub Class
The class.vb that I want to use as clsMain.MySubClass.
File: MySubClass.vb
Partial Public Class MySubClass
Inherits BaseCollection
Private Class MySubSubClass '(Used for custom properties and functions)
'More properties and Functions
End Class
End Sub
Public Class BaseCollection 'functionality of MySubClass
Public Function MyFunction1()
'Return Data
End Function
End Class
How Main Class is Used
Public Class UsageClass
Private myMainDataStructure as new clsMain
Private Sub GetSubClassList()
dim MyData as ArrayList = myMainDataStructure.MySubClass.MyFunction1()
'^^^ error on this line: MyFunction1() is not a member of project.clsMain.MySubClass^^^
End Sub
End Class
Instead of trying to make this a Partial Class, you should just make a Property containing an instance of that class.
Nested classes must be created and have instances, just like top level classes. By making a property within your main class, you can automatically create that instance in your main class constructor, and your code will work as expected.
Public Class clsMain
Public Property myIntProp as Integer
Public property myStrProp as String
'other properties
Public Property OtherFunctionality as MyOtherClass = New MyOtherClass()
Then just define the class in a separate file:
Public Class MyOtherClass
Public Sub MyFunction1()

How to get the class type in a inherited shared method

Folks;
Code looks like:
Public Class MasterA
Inherits Underling
End Class
Public Class MasterB
Inherits Underling
End Class
Public Mustinherit Class Underling
Sub DoSomething()
Me.GetType 'Using the instance, I can get the class.
end sub
Shared function() as ???? 'How can I define the return type based on the class that inherited me?
'Me.GetType 'Won't work as this is a shared function with no instance 'Me'
End Function
End class
OK. The question is: is there a way to get at the class type from within a shared function that was inherited by another class?
What I'm building is an XML serializer/desrializer as an inheritable class so that classes that inherit it can be serilized to an XML file, and back again. Rather than writing a serializer/deserializer for each type of class I want to do this with, I'd like to just inherit the functionality.
To do that, though, requires that I be able to ascertain the clas that inherited me in the shared function.
You could get the desired behavior with a generic base class, my VB is a little rusty so you might find stray parens or brackets. This would really be the only way to get a type reference to an inheriting class in a shared base class function.
Public Mustinherit Class Underling(Of T)
Sub DoSomething()
Me.GetType 'Using the instance, I can get the class.
end sub
Shared function() As T
' GetType(T) should get the type at this point
End Function
End class
Public Class MasterA
Inherits Underling(Of MasterA)
End Class
Public Class MasterB
Inherits Underling(Of MasterB)
End Class
As a side note it does seem like a rather weird solution to handle XmlSerialization rather than through your own serializer implementation or XmlSerializer

Error when passing friend class as type from public class to friend base class

Disclaimer: I am fairly new to working with generics so I am not entirely sure if what I am trying to do even makes sense or is possible.
I have a bunch of user controls in a project. All of these user controls share a similar property so I want to move it into a base class. The only difference is the return type of the property.
I have three classes interacting in this scenario. The first class is a base type, which inherits from CompositeControl and will be inherited by other classes in my project:
Friend Class MyBaseClass(Of T As {New})
Inherits CompositeControl
Private _someProperty As T = Nothing
Protected ReadOnly Property SomeProperty As T
Get
// dumbed down for the sake of example
If _someProperty Is Nothing Then
_someProperty = New T()
End If
Return _someProperty
End Get
End Property
End Class
Then I have this control class, which inherits from MyBaseClass:
Public Class MyControlClass
Inherits MyBaseClass(Of MyReturnTypeClass)
// snip...
End Class
And finally MyReturnTypeClass which is what the base's SomeProperty should return:
Friend Class MyReturnTypeClass
Public Property AutoProperty1 As Boolean = False
Public Property AutoProperty2 As String = String.Empty
// etc
End Class
When I attempt to build the project, I get this error from MyControlClass:
Inconsistent accessibility: type argument 'MyReturnTypeClass' is less accessible than Class 'MyControlClass'.
I need MyControlClass to be Public so it can be consumed by other projects, and I also want the MyBaseClass and MyReturnTypeClass to be Friend so they cannot be seen/used by consumers. Am I just missing some special keyword somewhere or is this not possible?
You cannot inherit from a base class that is less accessible than the derived class. So for instance, this won't work:
Friend Class MyBase
End Class
Public Class MyDerived
Inherits MyBase ' Won't compile because MyBase is less accessible
End Class
Therefore, since in your example, MyBaseClass(T) has is a friend type, but you are trying to inherit from it into a public MyControlClass type. Therefore, even if you took generics and MyReturnTypeClass out of the "equation", it still wouldn't work.
However, with generics, even if no member of the public interface of the class actually uses the generic type, the type must still be at least as accessible as the derived type. For instance:
Public Class MyBase(Of T)
' T not actually used at all
End Class
Friend Class MyOtherType
End Class
Public Class MyDerived
Inherits MyBase(MyOtherType) ' Won't compile because MyOtherType is less accessible
End Class
The base class must be at least as accessible as the derived class. This is a language restriction (see here).
If you intend to avoid MyBaseClass being instantiated by consumers, consider marking it Public MustInherit instead of Friend. Hope this helps.

VB.NET inheritance - do all properties in the derived classes have to be declared in the base class?

I'm refactoring, and have run into a roadblock.
Background:
I have a base class and several inherited derived classes. The derived classes don't always need to have the same properties. If any properties are shared among the derived classes, those properties would live at the base class level ('Contents', for example).
Similarly, GoodDocument below has 'GoodThings' but would not want/need to have 'BadThings'.
I want to treat instances of both 'GoodDocument' and 'BadDocument' as type 'Document'
public mustinherit class Document
public property Contents as string
public sub new()...
end class
public class GoodDocument
inherits Document
public property GoodThings as string
public sub new()...
end class
public class BadDocument
inherits Document
public property BadThings as string
public sub new()...
end class
The 'DocumentWriter' class will also have several derived classes: ('GoodDocumentWriter' and 'BadDocumentWriter').
I need to pass around the DocumentWriter.Doc as a 'Document' to a number of other places in the code. Doc.GoodThings would only be called from within an instance of either 'GoodDocument' or 'GoodDocumentWriter'.
public mustinherit class DocumentWriter
public property Doc as Document
public sub new()...
end class
public class GoodDocumentWriter
inherits DocumentWriter
public sub new
mybase.Doc = new GoodDocument
end sub
end class
public class BadDocumentWriter
inherits DocumentWriter
public sub new
mybase.Doc = new BadDocument
end sub
end class
Question:
Is there a design pattern that allows for derived classes to have members that don't exist at the base class level?
Do all properties have to live at the base class level?
Revised
I was trying to be brief with my initial question and I made the mistake of over simplifying the situation. In short, I did realize that it should be possible to have different properties on each of the derived classes. (I typed that in a tongue-in-cheek manor and didn't mean to keep it in the final post).
I realize now that the problem that I was experiencing was really symptomatic of a larger issue which needed addressing.
It appears that I was encountering compiler complaints that could be corrected by further refactoring and looser coupling. While others answered the basic question that I posed, Ryan Gross' example really helped kick start some new ideas.
Thanks!
What you should do in this case is define the operations that can be performed on instances of Document in an interface. In your case maybe there is a WriteThings operation, so you would have:
public interface Writeable {
public sub WriteThings();
}
Then in your derived classes you would implement the method to utilize the internal data of the class. For example:
public mustinherit class Document implements Writeable
public property Contents as string
public sub new()...
public sub WriteThings();
end class
public class GoodDocument
inherits Document
public property GoodThings as string
public sub new()...
public sub WriteThings()
//Do something with GoodThings
end sub
end class
public class BadDocument
inherits Document
public property BadThings as string
public sub WriteThings()
//Do something with BadThings
end sub
public sub new()...
end class
Finally, client code that needs to call WriteThings accesses it through an interface:
public mustinherit class DocumentWriter
public property Doc as Writable
public sub new()...
public sub PerformWrite()
Doc.WriteThings();
end sub
end class
It is generally not a good idea to build several parallel class hierarchies. In this case, one DocumentWriter class should be able to write any class that implements Writeable by invoking its WriteThings method.
If all the properties live at the base class level, then I'm not sure what the point of a derived class would be. :) You'd be able to do everything with the base class.
So, yes. If something is applicable only to GoodDocument and not to Document, then it should be in GoodDocument.
To answer your question specifically:
Yes, you just create multiple layers in the inheritance hierarchy: You have a base class, and then many two “branches” (good and bad, to use your terminology). Any properties that are only relevant to either branch, you declare in the class that inherits from the base class. Those properties will only be visible to that class and any classes inheriting from it.
No, properties can be declared anywhere within your inheritance hierarchy.