How to define an Action in an interface - vb.net

How can I define the StateChangedAction in an interface? I have the same Action on different controls, so I would be cleaner to work with a single interface.
Public class MyControl
Public StateChangedAction As Action(Of ControlState)
Public Sub New()
End Sub
End Class

Related

Why in VB.NET is not possible te declare a NotOverridable method?

I'm trying to avoid that sub-classes of my class can override my method.
If I try to do so by using the NotOverridable keyword:
Public Class Class1
Protected NotOverridable Sub DoSomething()
End Sub
End Class
I get this error:
'NotOverridable' cannot be specified on methods that do not override another method
Let's say that you have this class:
Public Class GrandParent
Protected Sub Method1()
End Sub
Protected Overridable Sub Method2()
End Sub
End Class
and then you have this class:
Public Class Parent
Inherits GrandParent
Protected Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
Parent.Method2 is overriding GrandParent.Method2, just as indicated. On the other hand, Parent.Method1 is NOT overriding GrandParent.Method1. That code generates the following warning:
sub 'Method1' shadows an overloadable member declared in the base
class 'GrandParent'. If you want to overload the base method, this
method must be declared 'Overloads'.
If you change the code to the following:
Public Class Parent
Inherits GrandParent
Protected Overrides Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
then you get the following error:
'Protected Overrides Sub Method1()' cannot override 'Protected Sub
Method1()' because it is not declared 'Overridable'.
Shadowing is different to overloading in that shadowing honours the type of the reference while overriding honours the type of the object. That means that, if you you have a Parent object assigned to a GrandParent variable, calling Method1 will invoke GrandParent.Method1 based on the type of the reference and calling Method2 will invoke Parent.Method2 based on the type of the object. Overriding implements polymorphism where shadowing does not. The first implementation of Parent is equivalent to this:
Public Class Parent
Inherits GrandParent
Protected Shadows Sub Method1()
End Sub
Protected Overrides Sub Method2()
End Sub
End Class
If you were to then add this class:
Public Class Child
Inherits Parent
Protected Overrides Sub Method2()
End Sub
End Class
it would work as expected. If you changed the Parent class to this:
Public Class Parent
Inherits GrandParent
Protected Shadows Sub Method1()
End Sub
Protected NotOverridable Overrides Sub Method2()
End Sub
End Class
then that `Child implementation would generate this error:
'Protected Overrides Sub Method2()' cannot override 'Protected
NotOverridable Overrides Sub Method2()' because it is declared
'NotOverridable'.
That is the only reason to use the NotOverridable keyword, i.e. to prevent derived classes overriding your own overridden implementation of an inherited member.

How to cast object of type 'especific' to type 'FileHelpers.Events.INotifyRead in Multirecording

I'm trying to centralize all formatting and conversion rule in a single class especific. Using the interface INotifyRead(Of T As Class). When I implement the methods BeforeRead/AfterRead throws an exception: Unable to cast object of type 'Especific' to type 'FileHelpers.Events.INotifyRead`1[System.Object]'.
Below my code.
Using engine As New MultiRecordEngine(New RecordTypeSelector(AddressOf CifraRecordTypeSelector),
GetType(RemessaRegistroCliente),
GetType(RemessaRegistroContrato))
Dim records = engine.ReadFile(_camArquivo)
End Using
Public NotInheritable Class RemessaRegistroCliente
Implements INotifyRead(Of RemessaRegistroCliente)
Public Sub AfterRead(e As AfterReadEventArgs(Of RemessaRegistroCliente)) Implements INotifyRead(Of RemessaRegistroCliente).AfterRead
End Sub
Public Sub BeforeRead(e As BeforeReadEventArgs(Of RemessaRegistroCliente)) Implements INotifyRead(Of RemessaRegistroCliente).BeforeRead
End Sub
End Class
Public NotInheritable Class RemessaRegistroContrato
Implements INotifyRead(Of RemessaRegistroContrato)
Public Sub AfterRead(e As AfterReadEventArgs(Of RemessaRegistroContrato)) Implements INotifyRead(Of RemessaRegistroContrato).AfterRead
End Sub
Public Sub BeforeRead(e As BeforeReadEventArgs(Of RemessaRegistroContrato)) Implements INotifyRead(Of RemessaRegistroContrato).BeforeRead
End Sub
End Class
Since MultiRecordEngine has no generic version, you cannot implement the generic INotifyRead(Of T) to handle events. Instead, assign delegates to the engine.
Sub Main()
Using engine As New MultiRecordEngine(New RecordTypeSelector(AddressOf CifraRecordTypeSelector),
GetType(RemessaRegistroCliente),
GetType(RemessaRegistroContrato))
AddHandler engine.BeforeReadRecord, AddressOf BeforeReadRecordHandler
End Using
End Sub
Private Sub BeforeReadRecordHandler(ByVal engine As EngineBase, ByVal e As BeforeReadEventArgs(Of Object))
End Sub
You'll also need to modify your classes to remove the generic interfaces:
Public NotInheritable Class RemessaRegistroCliente
'your fields
End Class
Public NotInheritable Class RemessaRegistroContrato
'your fields
End Class

Inner class Factory Method

I have tried to implement the Factory method with a trick, but for some reason is not working:
Public Class MetamodelElement
Public Class MetamodelElementFactoryBase
End Class
Private Sub New()
End Sub
End Class
Public Class MetamodelElementFactory : Inherits MetamodelElement.MetamodelElementFactoryBase
Function CreateMetamodelElement() As MetamodelElement
Return New MetamodelElement()
End Function
End Class
It says that the class does not have access to the private method (constructor).
I have followed an example from C# in this post:
Hidden Features of C#?
The compiler complains that you are trying to use the Private constructor from outside of the class. That is not allowed. So either make it Public or don't call it.
Public Class MetamodelElement
Public Class MetamodelElementFactoryBase
End Class
Public Sub New() ' <---- HERE!!! Now it works because it's public
End Sub
End Class
Public Class MetamodelElementFactory
Inherits MetamodelElement.MetamodelElementFactoryBase
Function CreateMetamodelElement() As MetamodelElement
Return New MetamodelElement() ' <--- HERE was the error
End Function
End Class
You can access private class members only from inside of the class.
MSDN: Access Levels
According to the C# code that you've linked you have to move the constructor into the class that you are inheriting from. Then you can also use Protected:
Public Class MetamodelElement
Public Class MetamodelElementFactoryBase
Protected Sub New()
End Sub
End Class
End Class

Defer (lazy creation) or suppress creation of Unity Call Handler Attributes until the decorated method is actually called

I am trying to use Interception Call Handler and Handler Attributes on my interfaces (or implementation). Lets say my Interface has two methods DoSomething() and DoSomethingElse(), and I only have the interceptor for DoSomethingElse(); when I resolve my main interface the constructor for the Call Handler get called even if I never invoke DoSomethingElse().
I tried this by resolving to Lazy(of IMainInterface) but the moment I call the function DoSomething() the Call Handler is still created unnecessarily. Is there a way to prevent this from happening either by code or configuration. Here is my sample implementation
Handler Attribute and Call Handler
<AttributeUsage(AttributeTargets.Method)>
Public Class NormalSampleAttribute
Inherits HandlerAttribute
Public Sub New()
Console.WriteLine("Constructor of Normal Sample Attribute")
End Sub
Public Overrides Function CreateHandler(container As Microsoft.Practices.Unity.IUnityContainer) As Microsoft.Practices.Unity.InterceptionExtension.ICallHandler
Console.WriteLine("Create Handler")
Return New SampleCallHandler
End Function
End Class
Public Class SampleCallHandler
Implements ICallHandler
Public Sub New()
Console.WriteLine("Constructor of Sample Call handler")
End Sub
Public Function Invoke(input As IMethodInvocation, getNext As GetNextHandlerDelegate) As IMethodReturn Implements ICallHandler.Invoke
Console.WriteLine("Invoke of Sample Call handler - " & input.MethodBase.Name)
Return getNext.Invoke(input, getNext)
End Function
Public Property Order As Integer Implements ICallHandler.Order
End Class
Interface and implementation
Public Interface IMainInterface
Sub DoSomething()
<NormalSample()>
Sub DoSomethingElse()
End Interface
Public Class MainClass
Implements IMainInterface
Public Sub New()
Console.WriteLine("main class - Constructor")
End Sub
Public Sub DoSomething() Implements IMainInterface.DoSomething
Console.WriteLine("main class do something...")
End Sub
Public Sub DoSomethingElse() Implements IMainInterface.DoSomethingElse
Console.WriteLine("main class do something else...")
End Sub
End Class
Main module to register and execute the method
Module Module1
Public container As IUnityContainer
Sub Main()
container = New UnityContainer
DoRegistrations()
Console.WriteLine("Before lazy Resolve")
Dim lmc As Lazy(Of IMainInterface) = container.Resolve(Of Lazy(Of IMainInterface))()
Console.WriteLine("Before making lazy function call")
lmc.Value.DoSomething()
Console.ReadLine()
End Sub
Sub DoRegistrations()
container.AddNewExtension(Of InterceptionExtension.Interception)()
container.RegisterType(Of IMainInterface, MainClass)()
container.Configure(Of Interception).SetDefaultInterceptorFor(Of IMainInterface)(New InterfaceInterceptor)
End Sub
End Module
It produces the following output:
Before lazy Resolve
Before making lazy function call
main class - Constructor
Constructor of Normal Sample Attribute
Create Handler
Constructor of Sample Call handler
main class do something...
Even though DoSomethingElse() is never called the cost of the handler creation is being added on all flows. Is there any way to avoid this? Any help is appreciated.
Thanks in advance!
SV

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