VB > Reflection.Emit: inherit from superclass and override method - vb.net

I've been trying to write this very simple code myself but I find it a bit difficult (Reflection.Emit is very new to me), so here I am.
What I need is an entire class that inherits from a super class and override a method - all written to be emitted and created in runtime.
My super class, ClassA, is an empty class without any code except for the Implement IDispose:
Namespace Basic
Public Class ClassA
Implements IDisposable
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace
My ClassB is the one to be created at runtime. It should look like this:
Namespace Basic
Public Class ClassB
Inherits ClassA
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
End Sub
End Class
End Namespace
I've been searching alot and I cannot find out how to write the inherit code, when creating ClassB on fly.
Also, I'm not that sure about writing the call-segment in the OPCode for ClassB
.method family strict virtual instance void
Dispose(bool disposing) cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: call instance void WindowsApplication1.Basic.ClassA::Dispose(bool)
IL_0008: nop
IL_0009: nop
IL_000a: ret
} // end of method ClassB::Dispose
Anyone?

This is what I neded up with.
This class holds the iDisposable:
Public Class Super
Implements IDisposable
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
For Each prop As PropertyInfo In Me.GetType.GetProperties
If prop.CanWrite Then
prop.SetValue(Me, Nothing, Nothing)
End If
Next
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Overridable Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
...and this is my class builder that inherits from Super
Public Class ClassCreator
Public Shared Function CreateClass() As Object
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
Thread.CurrentThread.CurrentUICulture = New CultureInfo("en-US")
Dim name As String = "DefineMethodOverrideExample"
Dim myAssemblyName As New AssemblyName(name)
Dim myAssemblyBuilder As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndSave)
Dim myModuleBuilder As ModuleBuilder = myAssemblyBuilder.DefineDynamicModule(name, name & ".dll")
Dim myTypebuilder As TypeBuilder = myModuleBuilder.DefineType("C", TypeAttributes.Public, GetType(Super))
Dim myMethodBuilder As MethodBuilder = myTypebuilder.DefineMethod("Dispose",
MethodAttributes.Public Or MethodAttributes.ReuseSlot Or MethodAttributes.Virtual Or MethodAttributes.HideBySig,
Nothing,
Type.EmptyTypes)
Dim il As ILGenerator = myMethodBuilder.GetILGenerator()
il = myMethodBuilder.GetILGenerator()
il.Emit(OpCodes.Nop)
il.Emit(OpCodes.Ldarg_0)
il.Emit(OpCodes.Call, GetType(Super).GetMethod("Dispose"))
il.Emit(OpCodes.Nop)
il.Emit(OpCodes.Nop)
il.Emit(OpCodes.Ret)
Dim tc As Type = myTypebuilder.CreateType()
myAssemblyBuilder.Save(name & ".dll")
Dim test As Object = Activator.CreateInstance(tc)
Return test
End Function
End Class
The class builder build classes that can be Disposed, which was what I wanted :)

Related

Can you get/change data of ALL instances of an object from within a shared function within a class?

Problem:
I have a class where I have a eventlog that logs for that particular instance of the class and logs to a shared eventlog and to track changes across all instances.
My issue is that I want the logs to be re sizable in their number of entries and I need to make sure that the shared log is never smaller than any of the instanced logs. Is it possible to check this?
What I've tried:
I've seen a-lot about GetType and reflections and I've been able to get instance names but I can't figure out how to reference data within those instances.
Below is a psuedocode of where I am at.
Public Class Test
Public InstancedLog As DataSet
Public Shared SharedLog As DataSet
Public Shared Sub ResizeSharedLog(ByRef DesiredSize As Integer)
If DesiredSize < ("check and sum up the size of all instances of InstancedLog") Then
'can't resize, too small.
Else
'resize to DesiredSize.
End If
End Sub
End Class
Any help would be much appreciated.
Here's an example of a class that tracks its own instances:
Public Class Class1
Implements IDisposable
Private Shared instances As New List(Of Class1)
Public Sub New()
instances.Add(Me)
End Sub
Public Shared Sub TouchEveryInstance()
For Each instance As Class1 In instances
'Use instance here.
Next
End Sub
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
instances.Remove(Me)
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
' TODO: uncomment the following line if Finalize() is overridden above.
' GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Most of that code is auto-generated by VS when you add the Implements IDisposable line. The entire region was added automatically except the line that refers to the instances field. I added the instances field, the constructor and the TouchEveryInstance method.

UDPClient Begin received packet source address

I have a service in VB.NET (2010) that is receiving a UDP packets with UDPClient.BeginReceive asynchronously.
Everything is working fine, I'm able to receive a packet data - but I'm not able to get sender (or remote) endpoint.
There is a CallBack routine that is receiving an IAsyncResult object, that is represented by System.net.sockets.OverlappedAsyncResult where in property SocketAddress is a byte array where is a sender port and sender IP address.
But it is accessible only in debug time - I'm using a breakpoint in async callback routine.
Im unable to cast IAsyncResult as OverlappedAsyncResult and I'm not able to access the socket address in design time. It is giving me an error that means that object is not found and it can't be declared.
I'm attaching a class that I use for it for reference. Is there any better way to do it, or can I get the sender IP?
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Public Class UDPInterface
Implements IDisposable
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
' TODO: set large fields to null.
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
Private _EP As UdpClient
Private _RemIPEP As System.Net.IPEndPoint
Private _Port As Integer
Public Sub New(Port As Integer)
_Port = Port
_RemIPEP = New IPEndPoint(System.Net.IPAddress.Any, Port)
_EP = New UdpClient
_EP.Client.Bind(_RemIPEP)
_EP.BeginReceive(AddressOf Receive, _EP)
End Sub
Public Sub SendPacket(Bytes As Byte())
_EP.Send(Bytes, Bytes.Length, New IPEndPoint(System.Net.IPAddress.Broadcast, _Port))
End Sub
Private Sub Receive(rec As IAsyncResult)
Dim RX As Byte() = _EP.EndReceive(rec, _RemIPEP)
Debug.Print(Encoding.ASCII.GetString(RX))
_EP.BeginReceive(AddressOf Receive, _EP)
RaiseEvent PacketReceived(RX)
End Sub
Public Event PacketReceived(Bytes As Byte())
End Class

Implementing IDisposable on a simple class

I wanted to make a helper class for my MySql wrapper. The idea is that the methods that encapsulate mysql command construction and execution have an optional MySqlConnection as an argument. If a specific connection is passed, it uses that, if not, it creates one and disposes of it once done. To save 4 lines off every method, I could use this class in the using block and pass the optional argument as a construction parameter. Anyway, heres the class:
Public Class DynaConnection
Implements IDisposable
Public Dynamic As Boolean
Public Connection As MySqlConnection
Public Sub New(Connection As MySqlConnection)
If Connection Is Nothing Then
Dynamic = True
Me.Connection = Connect()
Else
Dynamic = False
End If
End Sub
Public Shared Widening Operator CType(ByVal Connection As DynaConnection) As MySqlConnection
Return Connection.Connection
End Operator
Public Sub Dispose() Implements IDisposable.Dispose
If Dynamic Then
Connection.Close()
Connection.Dispose()
End If
GC.SuppressFinalize(Me)
End Sub
End Class
When I first wrote the letters "Implements IDisposable" though, a whole wall of code jumped into the class. I looked at msdn to see whats what but over there was an even longer bunch of code on how to "properly" implement IDisposable.
From what I remember from writing simple IDisposable classes before, what I've done in the class above should suffice. Has something changed?
This is that "wall of code" with some additional comments.
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects).
'If your class holds references to other .NET objects
'that themselves implement IDisposable then you should implement IDisposable
'and call their Dispose method in yours
End If
' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
'If you're holding any OS resources, e.g. file or image handles,
'then you should release them. That will be a rare thing for most people and can be pretty much ignored
' TODO: set large fields to null.
'If any of your fields may refer to objects that occupy
'a large amount of memory then those fields should be set to Nothing
End If
Me.disposedValue = True
End Sub
' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
'Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
' Dispose(False)
' MyBase.Finalize()
'End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
I agree with GSeng, this is the correct way to implement IDisposable.

VB.NET Do I need to close filestream at class finalize?

I have a class in which I have declared a FileStream and a StreamReader:
Option Strict Off
Option Explicit On
Friend Class clsFileReader
Private _fs As IO.FileStream
Private _sr As IO.StreamReader
I would like ask if I explicitely need to close these like this:
Protected Overrides Sub Finalize()
_fs.Close()
_sr.Close()
End Sub
... or if that is done automatically.
Thank you for the help!
ps: I can not use "using" because I want to read the file line by line like this:
Public Function ReadLine() As String
Debug.Assert(Not _sr.EndOfStream)
_sCurrentLineString = _sr.ReadLine
_iCurentLineIndex = _iCurentLineIndex + 1
Return _sCurrentLineString
End Function
I would suggest you use the same fonctionality as found in the stream. Implement the IDisposable interface and call .Dispose on your class instance when you're done with it. Same as you would do with a stream.
Here's a quick example.
Class clsFileReader : Implements IDisposable
Private _fs As IO.FileStream
Private _sr As IO.StreamReader
' Flag: Has Dispose already been called?
Dim disposed As Boolean = False
' Public implementation of Dispose pattern callable by consumers.
Public Sub Dispose() _
Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
' Protected implementation of Dispose pattern.
Protected Overridable Sub Dispose(disposing As Boolean)
If disposed Then Return
If disposing Then
' Free any other managed objects here.
'
_fs.Close()
_sr.Close()
End If
' Free any unmanaged objects here.
'
disposed = True
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
End Sub
End Class

Visual Studio/Resharper: Navigate to overriden method

I have a base class Base and a class Child which inherits from this base class. The base class is IDisposable.
I have a call to the Dispose method of the Child class. Is there a way to navigate to the overridden implementation in Child?
Dim oChild as Child
oChild.Dispose()
When I press F12 while having the Dispose() method selected, I end up in Base.Dispose() instead of Child.Dispose(). Note that the declaration is as the Child type.
P.S.: I do have ReSharper so if anyone would have an easy solution with ReSharper, that would work too.
Edit (code example):
Public Class CBase
Implements IDisposable
Private disposedValue As Boolean ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' Disposing etc.
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
End Class
Public Class CChild
Inherits CBase
Protected Overrides Sub Dispose(disposing As Boolean)
Try
If disposing Then
' Dispose child specific
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
End Class
Public Class CExample
Public Sub ProvideExample()
Dim oChild As New CChild
oChild.Dispose() ' F12 on this leads me to CBase.Dispose
End Sub
End Class
Is there any Code in der overridden method?
Because normally if you press F12 you are not getting up to the base. I think it's only if there is nothing else in the overridden method?