Interfaces & Sub-classes with different types - vb.net

I have the following situation, that I'm pretty sure can be solved through the use of interfaces, but am not quite experienced enough to implement and keep losing myself.
Public Class IPGateway
Property Hostname As String
Property Port As Integer
Public Function Read()
Return OtherClass.Read(Hostname, Port)
End Sub
End Class
Public Class SerialGateway
Property Port As String
Property Baud As Integer
Public Sub Read()
Return YetAnotherClass.Read(Port, Baud)
End Sub
End Class
Public Sub Main()
Dim GatewayList as New List(of Gateways?) <- Interface here?
GatewayList.Add(SerialGateway)
GatewayList.Add(IPGateway)
For each gateway in GatewayList
Console.Write(gateway.Hostname() OR gateway.Baud)
Console.Write(gateway.Read())
Next
End Sub
I would welcome advice on how to best implement this approach?

You have 2 choises, one with Abstract Classes (MustInherit for VB) and one with interfaces. You have to decide which one works best for you!
Module Module1
Sub Main()
Console.WriteLine("With Abstract Classes")
Dim GatewayList As New List(Of TheBase)
GatewayList.Add(New SerialGateway With {.Baud = 5, .Port = "10"})
GatewayList.Add(New IPGateway With {.Hostname = "Test", .Port = "15"})
For Each gateway In GatewayList
Console.WriteLine(gateway.Port)
If TypeOf gateway Is SerialGateway Then
Console.WriteLine(DirectCast(gateway, SerialGateway).Baud)
ElseIf TypeOf gateway Is IPGateway Then
Console.WriteLine(DirectCast(gateway, IPGateway).Hostname)
End If
Console.WriteLine(gateway.Read())
Next
Console.WriteLine("With Interface")
Dim GatewayList2 As New List(Of TestIn)
GatewayList2.Add(New SerialGateway2 With {.Baud = "5", .Port = "10"})
GatewayList2.Add(New IPGateway2 With {.Hostname = "Test", .Port = "15"})
For Each gateway As TestIn In GatewayList2
Console.WriteLine(gateway.Port)
Console.WriteLine(gateway.Property2)
Console.WriteLine(gateway.Read())
Next
Console.ReadLine()
End Sub
End Module
Public Class IPGateway
Inherits TheBase
Property Hostname As String
Public Overrides Function Read() As String
Return "IPGateway"
End Function
End Class
Public Class SerialGateway
Inherits TheBase
Property Baud As Integer
Public Overrides Function Read() As String
Return "SerialGateway"
End Function
End Class
Public MustInherit Class TheBase
Public Property Port As String
Public MustOverride Function Read() As String
End Class
Public Interface TestIn
Property Port As String
Property Property2 As String
Function Read() As String
End Interface
Public Class SerialGateway2
Implements TestIn
Public Property Port As String Implements TestIn.Port
Public Property Baud As String Implements TestIn.Property2
Public Function Read() As String Implements TestIn.Read
Return "SerialGateway2"
End Function
End Class
Public Class IPGateway2
Implements TestIn
Public Property Port As String Implements TestIn.Port
Public Property Hostname As String Implements TestIn.Property2
Public Function Read() As String Implements TestIn.Read
Return "IPGateway2"
End Function
End Class

Related

VB if base class implements interface, does the derived class also need to implement?

I was analyzing a code. There we have a base class (not abstract) implementing an interface. Then we have a derived class of the base class which also implements the interface.
Interface:
Public Interface MainInterface
Function getMetaThreads(ByVal ThreadCount As Integer) As String()
Property Name() As String
Property TargetDirectory() As String
Property TimeOut() As Long
ReadOnly Property ExecutableAssembly() As String
ReadOnly Property IsVersionValid() As Boolean
End Interface
Base class:
Public Class BaseClass
Implements MainInterface
Public Sub print()
Console.WriteLine("BaseClass printing")
End Sub
Public ReadOnly Property ExecutableAssembly As String Implements MainInterface.ExecutableAssembly
...
End Property
Public ReadOnly Property IsVersionValid As Boolean Implements MainInterface.IsVersionValid
...
End Property
Protected strName As String = ""
Protected strTargetDirectory As String = ""
Protected lngTimeout As Long = 0
Public Property Name As String Implements MainInterface.Name
...
End Property
Public Property TargetDirectory As String Implements MainInterface.TargetDirectory
...
End Property
Public Property TimeOut As Long Implements MainInterface.TimeOut
...
End Property
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
...
End Function
Public Overridable Function myOwnFunc() As String
Return ""
End Function
End Class
Derived Class:
Public Class SubClass
Inherits BaseClass
Implements MainInterface
Public Function getMetaThreads(ThreadCount As Integer) As String() Implements MainInterface.getMetaThreads
Return myOwnFunc()
End Function
Overrides Function myOwnFunc() As String()
Dim l As New List (Of String)
l.Add("44")
l.Add("33")
return l.ToArray()
End Function
End Class
Does it make sense to implement the interface in the derived class again? Is there a reason or a case where this becomes necessary? I think that having the base class implement the interface should be enough and implementing it in the interface is redundant.

CodeAccessSecurityAttribute derived class throwing System.TypeLoadException (Failure has occurred while loading a type)

I have custom attribute applied to CRUD repository methods to control access:
Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext)
Inherits DbContextGenericRepository(Of TEntity, TContext)
Public Sub New(connectionService As IConnectionService)
MyBase.New(connectionService)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Delete(ParamArray entities() As TEntity)
MyBase.Delete(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Insert(ParamArray entities() As TEntity)
MyBase.Insert(entities)
End Sub
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)>
Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity)
Return MyBase.Select(predicate)
End Function
<EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
Public Overrides Sub Update(ParamArray entities() As TEntity)
MyBase.Update(entities)
End Sub
End Class
This is implementation of attribute:
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Property EmployeeRoles As EmployeeRoles
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
And permission:
Public Class EmployeeRolePermission
Implements IPermission
Public Sub New(employeeRoles As EmployeeRoles)
_EmployeeRoles = employeeRoles
End Sub
Public Function Copy() As IPermission Implements IPermission.Copy
Return New EmployeeRolePermission(_EmployeeRoles)
End Function
Public Sub Demand() Implements IPermission.Demand
Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal)
If Not principal.IsInRole(_EmployeeRoles) Then
Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound,
principal.Identity.Name,
_EmployeeRoles.ToString()))
End If
End Sub
Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml
Throw New NotImplementedException()
End Sub
Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect
Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf
Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml
Throw New NotImplementedException()
End Function
Public Function Union(target As IPermission) As IPermission Implements IPermission.Union
Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles)
End Function
Public ReadOnly Property EmployeeRoles As EmployeeRoles
End Class
Every time one of the CRUD methods are reached, TypeLoadException is thrown. I really dont know cause of this, but if I remove attributes from CRUD methods, everything works fine.
This seems to be due to the enum-valued property on the attribute (see https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception for details). To work around this issue, you could use a string-valued property on the attribute and cast to an enum either in the property setter or just before creating the permission. (Personally, I'd probably opt for the former in the interests of enabling early validation, but ymmv...)
Another workaround is making attribute property of type, which is used in Enum, in this case Integer.
Public Class EmployeeRoleRequirementAttribute
Inherits CodeAccessSecurityAttribute
Public Sub New(action As SecurityAction)
MyBase.New(action)
End Sub
Public Overrides Function CreatePermission() As IPermission
Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles))
End Function
Public Property RequiredEmployeeRoles As Integer
End Class
<Flags>
Public Enum EmployeeRoles As Integer
DataReader = 0
DataWriter = 1
End Enum
Then you dont need to use String, which does not allow easy combining of flags when attribute is used:
<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)>
Sub SecuredMethod()
End Sub

Incompatible interface

Please see the code below:
Public Class clsCar
Implements IVehicle
Public Function getWheels() As Integer Implements IVehicle.getWheels
Return 4
End Function
End Class
Public Interface IVehicle
Function getWheels() As Integer
End Interface
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim list As List(Of IVehicle) = New List(Of IVehicle)
Dim v1 As IVehicle = New clsCar
Dim v2 As IVehicle = New clsBus
list.Add(v1)
list.Add(v2)
Dim IVehicle As IVehicle = New clsCar
Dim IVehicle2 As IVehicle = New clsBus
For Each IVehicle In list
MsgBox(IVehicle.getWheels())
Next
End Sub
End Class
I want to add a new function to the clsBus class:
Public Function getWheels(ByVal strCarType As String) As Integer
If strCarType = "Robin Ryliant" Then
Return 3
Else
Return 4
End If
End Function
How do I call this from the FOR EACH statement? At the moment it will call getWheels with no arguments.
You will have to add the method overload to the interface in order to be able to call it from a IVehicle variable.
Public Interface IVehicle
Function getWheels() As Integer
Function getWheels(ByVal strCarType As String) As Integer
End Interface
But probably it is better to have different, more specialized car types
Public Class clsCar
Implements IVehicle
Public Overridable Function getWheels() As Integer Implements IVehicle.getWheels
Return 4
End Function
End Class
Public Class clsRobinRyliantCar
Inherits clsCar
Public Overrides Function getWheels() As Integer
Return 3
End Function
End Class
This does not break the inheritance hierarchy and is purely polymorphic.
I think I would go for something more like this, with the number of wheels being an instance property (code in LINQPad format):
Sub Main
Dim list As List(Of IVehicle) = New List(Of IVehicle)()
list.Add(New clsCar("Ford Focus", 4))
list.Add(New clsCar("Robin Ryliant", 3))
list.Add(New clsBus())
For Each v In list
Console.WriteLine(String.Format("{0}:{1}", v.GetVehicleType(), v.GetWheels()))
Next
End Sub
' Define other methods and classes here
Public Interface IVehicle
Function GetVehicleType() As String
Function GetWheels() As Integer
End Interface
Public MustInherit Class clsVehicle
Implements IVehicle
Protected Property VehicleType As String
Protected Property Wheels As Integer
Protected Sub New(vehicleType As String, wheels As Integer)
Me.VehicleType = vehicleType
Me.Wheels = wheels
End Sub
Public Function GetVehicleType() As String Implements IVehicle.GetVehicleType
Return Me.VehicleType
End Function
Public Function GetWheels() As Integer Implements IVehicle.GetWheels
Return Me.Wheels
End Function
End Class
Public Class clsCar
Inherits clsVehicle
Public Sub New(vehicleType As String, wheels As Integer)
MyBase.New(vehicleType, wheels)
End Sub
End Class
Public Class clsBus
Inherits clsVehicle
Public Sub New()
MyBase.New("Bus", 4)
End Sub
End Class
If your clsBus and clsCar are meant to refer to a specific car then the type should be a member of that class already, not something you pass in when you want to get information. To this end I'd suggest that you have "type" as something you can pass in the constructor and then the method on the bus would have no parameters and would just refer to its internal type to determine how many wheels it has.
I'm not too fluent with VB.NET so would probably make mistakes in example code but hopefully you get what I mean. If not I'll knock up some code. :)

ServiceStack cache in VB.net

How do I go about implementing ServiceStack cache in VB.net? I've seen many C# examples, but I am not able to transfer this onto vb.net.
The point I get stack in the 1st and 2nd argument of the ServiceStack.ServiceHost.RequestContextExtensions.ToOptimizedResultUsingCache
1st should be: ServiceStack.ServiceHost.IRequestContext - not sure
what IRequestContext is
2nd should be:
ServiceStack.CacheAccess.Providers.MemoryCacheClient - how do I set
this do cache default in config i.e. MemoryCacheClient
Code below, any suggestion much appreciated.
Global.asax.vb
Public Class Global_asax
Inherits System.Web.HttpApplication
Public Class HelloAppHost
Inherits AppHostBase
Public Sub New()
MyBase.New("Web Services", GetType(Wrapper).Assembly)
End Sub
Public Overrides Sub Configure(ByVal container As Container)
Routes.Add(Of GetProduct)("/GetProduct").Add(Of GetProduct)("/GetProduct/{*}")
Plugins.Add(New Cors.CorsFeature(allowedHeaders:="Content-Type, Authorization"))
container.Register(Of ICacheClient)(New MemoryCacheClient())
End Sub
End Class
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Dim apphost = New HelloAppHost()
apphost.Init()
End Sub
End Class
WS.vb
Public Class Wrapper
Public Class WrapperGetProduct
Implements IService(Of GetProduct)
Public Function Execute(ByVal request As GetProduct) As Object Implements ServiceStack.ServiceHost.IService(Of GetProduct).Execute
Dim cachekey As String = "some_key"
Dim expireInTimespan = New TimeSpan(1, 0, 0)
Return ServiceStack.ServiceHost.RequestContextExtensions.ToOptimizedResultUsingCache(
ServiceStack.ServiceHost.IRequestContext, // not sure what this should be
ServiceStack.CacheAccess.Providers.MemoryCacheClient, // not sure what this should be - how do I set this to cache setted in configuration (in memory cache)?
cachekey, expireInTimespan,
Function() request.HandleRequest()
)
End Function
End Class
End Class
Use the new API
ToOptimizedResultUsingCache is an extension method for RequestContext which services inherit/expose, same with Cache (resolved automatically via IOC).
Example below converted from C#, caching/wrapping an existing service (AppConfig and Repository are resolved via IOC, registered in AppHost configure method).
Imports System.Collections.Generic
Imports ServiceStack.Common
Imports ServiceStack.ServiceHost
Imports ServiceStack.ServiceInterface.ServiceModel
Imports ServiceStack.Common.Web
Public Class SearchTerm
Public Property Latitude() As Double
Get
Return m_Latitude
End Get
Set
m_Latitude = Value
End Set
End Property
Private m_Latitude As Double
Public Property Longitude() As Double
Get
Return m_Longitude
End Get
Set
m_Longitude = Value
End Set
End Property
Private m_Longitude As Double
Public Property Term() As String
Get
Return m_Term
End Get
Set
m_Term = Value
End Set
End Property
Private m_Term As String
End Class
<Route("/lookup/searchterm", "GET")> _
Public Class SearchTermRequest
Implements IReturn(Of SearchTermResponse)
Public Property Term() As String
Get
Return m_Term
End Get
Set
m_Term = Value
End Set
End Property
Private m_Term As String
End Class
Public Class SearchTermResponse
Implements IHasResponseStatus
Public Property ResponseStatus() As ResponseStatus
Get
Return m_ResponseStatus
End Get
Set
m_ResponseStatus = Value
End Set
End Property
Private m_ResponseStatus As ResponseStatus
Public Property Results() As List(Of SearchTerm)
Get
Return m_Results
End Get
Set
m_Results = Value
End Set
End Property
Private m_Results As List(Of SearchTerm)
End Class
<Route("/cached/lookup/searchterm")> _
Public Class CachedSearchTermRequest
Implements IReturn(Of CachedSearchTermResponse)
Public ReadOnly Property CacheKey() As String
Get
Return UrnId.Create(Of CachedSearchTermRequest)(String.Format("{0}", Me.Term))
End Get
End Property
Public Property Term() As String
Get
Return m_Term
End Get
Set
m_Term = Value
End Set
End Property
Private m_Term As String
End Class
Public Class CachedSearchTermResponse
Implements IHasResponseStatus
Public Property ResponseStatus() As ResponseStatus
Get
Return m_ResponseStatus
End Get
Set
m_ResponseStatus = Value
End Set
End Property
Private m_ResponseStatus As ResponseStatus
Public Property Results() As List(Of SearchTerm)
Get
Return m_Results
End Get
Set
m_Results = Value
End Set
End Property
Private m_Results As List(Of SearchTerm)
End Class
Public Class SearchTermService
Inherits Service
Public Property Repository() As IRepository
Get
Return m_Repository
End Get
Set
m_Repository = Value
End Set
End Property
Private m_Repository As IRepository
Public Function [Get](request As SearchTermRequest) As SearchTermResponse
Return New SearchTermResponse() With { _
Key .Results = Me.Repository.SearchTermGet(request) _
}
End Function
End Class
Public Class CachedSearchTermService
Inherits Service
Public Property AppConfig() As AppConfig
Get
Return m_AppConfig
End Get
Set
m_AppConfig = Value
End Set
End Property
Private m_AppConfig As AppConfig
Public Function [Get](request As CachedSearchTermRequest) As Object
Dim cacheKey As String = request.CacheKey
Return Me.RequestContext.ToOptimizedResultUsingCache(
MyBase.Cache, cacheKey, New TimeSpan(0, Me.AppConfig.CacheTimeMinutes, 0),
Function()
Using service = Me.ResolveService(Of SearchTermService)()
Return service.[Get](request.TranslateTo(Of SearchTermRequest)()).TranslateTo(Of CachedSearchTermResponse)()
End Using
End Function
)
End Function
End Class

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 ...