generic Interface vb - vb.net

Trying to get my head around generic interfaces and classes. How do I 'get T' when using my class in the new method and call data.method using this type?
Public MustInherit Class RepositoryBase(Of T)
Implements IRepository(Of T)
Private Data As IDAL
Public Sub New()
Data = DTOParserFactory.GetParser(T.GetType().ToString())
End Sub
Public Sub delete(BaseDTO As T) Implements Domain.Business.IRepository(Of T).delete
'Data.delete(Convert.ChangeType(BaseDTO, TypeOf(Type))
End Sub
Public Function getAll() As System.Linq.IQueryable(Of T) Implements Domain.Business.IRepository(Of T).getAll
'Return Data.getAll()()
End Function
End Class

I'm assuming you need to get the Type object for T?
In your constructor
Public Sub New()
Data = DTOParserFactory.GetParser(GetType(T).ToString())
End Sub

I'm not super clear on the question, but perhaps this is what you are looking for.
Assuming you have a common base class BaseDTO then you would define your RepositoryBase class like this:
Public MustInherit Class RepositoryBase(Of T As BaseDTO)
Then you declare an instace of the class like this:
Dim userRepository As New RepositoryBase(Of User)()
What this does is constrain T to be a subclass of BaseDTO, and gives you access to all of BaseDTO's methods.

Related

Inheritance confusion vb.net

I searched over 20 articles and I am still slightly confused with inheritance. I have three classes as such:
Class A
Private _Mode As String
Public Function returnMode() As String
Return _Mode
End Function
Class B
Inherits Class A
Private _Mode As String = "modeb"
Class C
Inherits Class A
Private _Mode As String = "modec"
Now any time I create a B or C class, I would like the object to return the child class _Mode. I can make the New() function _Mode = "modeb" but I wanted to know a better way or more correct way.
How do I properly declare the variable _Mode?
One option would be to make _Mode Protected instead of Private so you can set it from the subclasses, and set the value is the subclass constructors:
Class A
Protected _Mode As String
Public Function returnMode() As String
Return _Mode
End Function
Class B
Inherits Class A
Public Sub New()
_Mode = "modeb"
End Sub
Class C
Inherits Class A
Public Sub New()
_Mode = "modec"
End Sub

VB.NET Inheritance issue

I've got A base class Base and Sorter and Parser classes derived from it .
The same thing with BaseResult with derived SorterResult and ParserResult.
Base has a Result field of BaseResult type, BaseResult has a Log field.
The reason why I've used a Base class, is because both of Parser and Sorter must write a Log.
Here's my code:
Public MustInherit Class Base
Public Result As BaseResult
Event LogChanged()
Protected Sub AddLogLine(ByVal _logString As String)
If Not String.IsNullOrWhiteSpace(_logString) Then Result.Log.Add(_logString)
RaiseEvent LogChanged()
End Sub
End Class
Public Class Sorter
Inherits Base
Public Shadows Result As SorterResult
Sub New()
Result = New SorterResult With {.Log = New List(Of String)}
End Sub
Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
Public Class Parser
Inherits Base
Public Shadows Result As ParserResult
Sub New()
Result = New ParserResult With {.Log = New List(Of String)}
End Sub
Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
Public MustInherit Class BaseResult
Public Log As List(Of String)
End Class
Public Class SorterResult
Inherits BaseResult
'//SorterResult fields
End Class
Public Class ParserResult
Inherits BaseResult
'//ParsedResult fields
End Class
The issue here is that compiler sais(on pic below):
"variable 'Result' conflicts with variable 'Result' in the base class 'Base' and should be declared 'Shadows'." When I used Shadows keyword, warning disappeared, but I get a null reference exception on this line, because Result field is Nothing:
If Not String.IsNullOrWhiteSpace(_logString) Then Result.Log.Add(_logString)
I can't assign a value to a Result variable in Base class constructor, because It must be of type SorterResult in Sorter, and ParserResult in Parser. What is the regular pattern here? Sorry my bad english.
Use generics
Public MustInherit Class Base(Of TResult As BaseResult)
Public Result As TResult
Event LogChanged()
Protected Sub AddLogLine(ByVal _logString As String)
If Not String.IsNullOrEmpty(_logString) Then Result.Log.Add(_logString)
RaiseEvent LogChanged()
End Sub
Public MustOverride Sub Go()
End Class
Public Class Sorter
Inherits Base(Of SorterResult)
Sub New()
Result = New SorterResult With {.Log = New List(Of String)}
End Sub
Public Overrides Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
Public Class Parser
Inherits Base(Of ParserResult)
Sub New()
Result = New ParserResult With {.Log = New List(Of String)}
End Sub
Public Overrides Sub Go()
AddLogLine("Sorter started")
End Sub
End Class
However, this is not a "beautiful" inheritance hierarchy. Inheritance should formulate relations like "a student is a person" where student derives from person. What do sorters and parsers have in common? Are they a Base? Are they loggers? Are they commands (as suggests the Go method)? Is inheritance required here? Wouldn’t it be more appropriate to use aggregation? I would declare a completely independent logger class and inject it into classes. This allows you to be more flexible, as it enables you to inject different types of loggers.
Public MustInherit Class Logger
Public Event LogChanged()
Public MustOverride Sub AddLogLine(ByVal message As String)
Protected Sub OnLogChanged()
RaiseEvent LogChanged()
End Sub
End Class
Public Class TextFileLogger
Inherits Logger
Public Overrides Sub AddLogLine(ByVal message As String)
If Not String.IsNullOrEmpty(message) Then
'TODO: Write message to log file
OnLogChanged()
End If
End Sub
End Class
You can inject it like this:
Public Class SomeConsumerClass
Private _logger As Logger
Sub New(ByVal logger As Logger)
_logger = logger
End Sub
Public Sub DoSomething()
_logger.AddLogLine("Did something!")
End Sub
End Class
Use like this:
Dim obj As New SomeConsumerClass(New TextFileLogger())
obj.DoSomething()
If you have another kind of logger (XmlFileLogger, StringListLogger, DatabaseLogger...) it is now easy to use it without having to change all the classes using it.
Maybe you should even have only one global logger:
Dim globalLogger As New TextFileLogger()
Dim sorter As New Sorter(globalLogger)
Dim parser As New Parser(globalLogger)

VB generics with constraints -- type casting and inheritance?

Take this scenario:
Public Interface IMyClass
End Interface
Public mustinherit class MyBaseClass : implements IMyClass
End Class
public class MyClass : inherits MyBaseClass
End Class
public class MyModel(of t as IMyClass)
private Dim _parameter as t
Public Sub New(byval parameter As t)
_parameter As t
End Sub
End class
In my controller, I can do this with no problem:
Dim _myclass as IMyClass = new MyClass()
Can I do something similar with this:
Dim _myModel as MyModel(of IMyClass) = new MyModel(of MyClass)
???
My initial thought was wrong, as I thought the conversion could be done automatically, but it appears it is not done. Any way to achieve the same thing within .NET?
EDIT
I updated the MyModel class to show more of what I was doing. I want to constrain the instance I create, but then do what would be a narrowing conversion with traditional, non-generics code. Basically, my partial Razor views would require the explicit model, and those views end up rendering another view that will take that model and display it. Because the models all implement or inherit a class that implements IMyClass, all the methods should exist on all of the instances and should be callable but the types are not interchangable.
Let’s modify MyModel slightly, shall we?
Public Class MyModel(Of T As IMyClass)
Private _parameter As T
Public Sub Something(parameter As T)
_parameter = parameter
End Sub
End class
Public Class MyClassA : Inherits MyBaseClass
End Class
Public Class MyClassB : Inherits MyBaseClass
End Class
Dim _myModel As MyModel(Of IMyClass) = New MyModel(Of MyClassA)()
_myModel.Something(New MyClassB()) ' Boom!
If the assignment were allowed the last line would pose a problem: MyMode(Of MyClassA)._parameter has type MyClassA but the last line would assign an object of the (unrelated) type MyClassB. This is illegal and so VB forbids it.
Do you need multiple varieties of MyModel, or are you just attempting to require that the stored object be constrained to IMyClass?
Simplest approach (that might not do everything you need):
Public Interface IMyClass
Sub DoIt()
End Interface
Public Class MyModel
Private ReadOnly _parameter As IMyClass
Public Sub New(parameter As IMyClass)
_parameter = parameter
End Sub
Public Sub DoItToIt()
_parameter.DoIt()
End Sub
End Class
Public Class MyClassA
Implements IMyClass
Public Sub DoIt() Implements IMyClass.DoIt
End Sub
End Class
Public Class Tests
Public Sub Main()
Dim model1 As MyModel = New MyModel(New MyClassA)
model1.DoItToIt()
End Sub
End Class
Next step up in complexity is to define an interface IHasMyClass for classes that contain an IMyClass. This supports manipulations based on the allowed type, and the actual type, of the contained object:
Public Interface IMyClass
Sub DoIt()
End Interface
Public Interface IHasMyClass
Function GetIt() As IMyClass
Function GetItsType() As Type
Function GetAllowedType() As Type
End Interface
Public Class MyModel(Of T As IMyClass)
Implements IHasMyClass
Private ReadOnly _parameter As IMyClass
Public Sub New(parameter As IMyClass)
_parameter = parameter
End Sub
Public Sub DoItToIt()
_parameter.DoIt()
End Sub
Public Function GetItAsT() As T
Return _parameter
End Function
Public Function GetIt() As IMyClass Implements IHasMyClass.GetIt
Return _parameter
End Function
Public Function GetItsType() As Type Implements IHasMyClass.GetItsType
Return _parameter.GetType()
End Function
Public Function GetAllowedType() As Type Implements IHasMyClass.GetAllowedType
Return GetType(T)
End Function
End Class
Public Class MyClassA
Implements IMyClass
Public Sub DoIt() Implements IMyClass.DoIt
End Sub
End Class
Public Class Tests
Public Sub Main()
' Allow any IMyClass
Dim model1 As MyModel(Of IMyClass) = New MyModel(Of IMyClass)(New MyClassA)
model1.DoItToIt()
Dim it As IMyClass = model1.GetIt()
Dim allowedT As Type = model1.GetAllowedType()
' Restrict to MyClassA
Dim modelA As MyModel(Of MyClassA) = New MyModel(Of MyClassA)(New MyClassA)
modelA.DoItToIt()
Dim itA1 As IMyClass = modelA.GetIt()
Dim itA2 As MyClassA = modelA.GetItAsT()
Dim allowedTA As Type = modelA.GetAllowedType()
End Sub
End Class
In Tests(), notice that we now need to declare whether we are creating a MyModel that accepts ANY IMyClass MyModel(Of IMyClass), or one that requires a specific sub-class MyModel(Of MyClassA).
If we want to manipulate MyModels, that may be either of the above types, we use the common interface:
Dim model As IHasMyClass
model = model1
...
model = modelA
Or in your case, to support all the functionality of MyModel, rename IHasMyClass as IMyModel, and add the various MyModel functions, but instead of T, use IMyClass:
Public Interface IMyModel
Function GetIt() As IMyClass
Function GetItsType() As Type
Function GetAllowedType() As Type
Sub DoItToIt()
Function CompareIt(other As IMyClass) As Integer
End Interface
And make appropriate changes/additions to IMyClass and MyModel.
Then it becomes possible to do:
Dim model As IMyModel = modelA
If model.CompareIt(model1.GetIt()) > 0 ...

Similar classes with different signatures

I have two classes:
Public Class Subscribing
Private _subscribingObjects As IList(Of String)
Public Sub Add(ByVal obj As SubscribeObject)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Public Class Providing
Private _providingObjects As IList(Of String)
Public Sub Add(ByVal obj As ProvideObject)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Is there a more elegant way to add do this? One class would suffice, but since the Add methods have different arguments, then one really wouldn't work.
Any help would be appreciated.
this?
Public Class SubscribingProviding(Of t)
Private _subscribingObjects As IList(Of String)
Public Sub Add(ByVal obj As t)
'...code...'
End Sub
Public Sub Remove(ByVal index As Integer)
'...code...'
End Sub
End Class
Your add functions should be fine. As long as you have different variable types being passed in you can have the function names be the same. Your remove Subs will not be allowed in the same class because it is using the same parameter Integer.
Eh.. probably not. They are different enough that you cant even Interface them.
I personally wouldn't mix the two responsibilities (of subscribing and providing) in one class. The classes themselves can easily be simplified by just inheriting from List(Of T)
Public Class Subscribing
Inherits List(Of SubscribeObject)
End Class
Public Class Providing
Inherits List(Of ProvideObject)
End Class
If you really want to get down to one class and make sure that it can only accept SubscribeObject and ProvideObject respectively, implement a common interface in both SubscribeObject and ProvideObject. Then create a generic class that accepts the interface:
' Common interface '
Public Interface ISubscribeProvideObject
End Interface
' SubscribeObject and ProvideObject both implementing the common interface '
Public Class SubscribeObject
Implements ISubscribeProvideObject
'...'
End Class
Public Class ProvideObject
Implements ISubscribeProvideObject
'...'
End Class
' Generic class accepting both types '
Public Class SubscribingProviding(Of T As ISubscribeProvideObject)
Inherits List(Of T)
'... Add() and Remove() methods only needed if custom logic applies ...'
End Class

Can I inherit from a generic class without specifying a type?

I have the following sample code in a VB.NET console application. It compiles and works, but feels like a hack. Is there a way to define EmptyChild so that it inherits from Intermediate(Of T As Class) without using the dummy EmptyClass?
Module Module1
Sub Main()
Dim Child1 = New RealChild()
Child1.Content = New RealClass()
Dim Child2 = New EmptyChild()
Console.WriteLine("RealChild says: " & Child1.Test)
Console.WriteLine("EmptyChild says: " & Child2.Test)
Console.ReadLine()
End Sub
Public Class EmptyClass
End Class
Public Class RealClass
Public Overrides Function ToString() As String
Return "This is the RealClass"
End Function
End Class
Public MustInherit Class Base(Of T As Class)
Private _content As T = Nothing
Public Property Content() As T
Get
Return _content
End Get
Set(ByVal value As T)
_content = value
End Set
End Property
Public Overridable Function Test() As String
If Me._content IsNot Nothing Then
Return Me._content.ToString
Else
Return "Content not initialized."
End If
End Function
End Class
Public MustInherit Class Intermediate(Of T As Class)
Inherits Base(Of T)
'some methods/properties here needed by Child classes
End Class
Public Class RealChild
Inherits Intermediate(Of RealClass)
'This class needs all functionality from Intermediate.
End Class
Public Class EmptyChild
Inherits Intermediate(Of EmptyClass)
'This class needs some functionality from Intermediate,
' but not the Content as T property.
Public Overrides Function Test() As String
Return "We don't care about Content property or Type T here."
End Function
End Class
End Module
The other way to do this would be to move the generic code out of the Base class and then create 2 Intermediate classes like this:
Public MustInherit Class Intermediate
Inherits Base
'some methods/properties here needed by Child classes
End Class
Public MustInherit Class Intermediate(Of T As Class)
Inherits Intermediate
'implement generic Content property here
End Class
Then RealChild would inherit from the generic Intermediate and EmptyChild would inherit from the non-generic Intermediate. My problem with that solution is that the Base class is in a separate assembly and I need to keep the code that handles the generic type in that assembly. And there is functionality in the Intermediate class that does not belong in the assembly with the Base class.
Yes, you need to specify a type parameter when you inherit, or your EmptyChild must be generic as well. But, you don't have to dummy up a EmptyClass - just use Object as your type parameter:
Public Class EmptyClass
Inherits Intermediate(Of Object)
End Class