VB.NET: Use property as delegate function - properties

I have got a problem with converting an example from C# to VB.NET.
The C# example has the following structure.
First there is a public delegate.
public delegate void CustomEventHandler(object sender , EventArgs e);
This delegate is connected to an property of an interface.
public interface ICustom {
CustomEventHandler MyProperty { get; set; }
}
Finally I have got a class with a function containing the interface as parameter. This property is called with the parameters like a function.
public class Test {
public void MySub(ICustom custom) {
custom.MyProperty(this, new EventArgs()); }
}
I can convert this code except for the use of the property. My VB.NET code looks like the following:
Public Delegate Sub CustomEventHandler(ByVal sender As Object, ByVal e As EventArgs)
Public Interface ICustom
Property MyProperty As CustomEventHandler
End Interface
Public Class Test
Public Sub MySub(ByVal custom As ICustom)
... How can I add here the event OnEvent to the event custom.MyEvent? ...
End Sub
End Class
Is it possible to convert this or is there another way necessary.
Thanks for any response.

For firing events in VB.NET you have to use RaiseEvent
http://msdn.microsoft.com/en-us/library/edzehd2t.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

Related

How works extensions method in VB.net with an interface as a object

I am struggling with an extension method in VB.NET, but I can't find why I can't implement this (I came from C# and I still having issues like this between language specification and how the language works, sorry if this question is too newbie):
namespace FakeBusiness.BusinessInterface
{
public interface IBusiness
{
int Id { get; set; }
string Name { get; set; }
}
}
namespace FakeBusiness.SharedExtensions
{
using FakeBusiness.BusinessInterface;
public static class ExtensionsMethods
{
public static bool IsEmpty(this IBusiness theObject)
{
return theObject != null && theObject.Id != 0;
}
}
}
namespace FakeBusiness.BusinessLogic
{
using FakeBusiness.BusinessInterface;
using FakeBusiness.SharedExtensions;
public class Business : IBusiness
{
public int Id { get; set; }
public String Name { get; set; }
}
public static class Program
{
public static void Main(string[] args)
{
IBusiness obj = new Business();
Console.WriteLine($"The object is: {(obj.IsEmpty() ? "empty" : "not empty")}");
}
}
}
And I want to achieve the same logic but for a reason VB.NET says 'Cannot resolve the symbol' even if I import explicitly the namespace from the extension method:
Namespace FakeBusiness.SharedExtensions {
<Extension()>
Public Function IsBusinessObjectEmtpy(ByVal business As IBusiness) As Boolean
Return (business IsNot Nothing AndAlso business.Id = 0)
End Function
End Namespace
Namespace FakeBusiness.BusinessLogic
Public Class BusinessObject : Implements IBusiness
Property Id As Integer Implements IBusiness.Id
Property Name As String Implements IBusiness.Name
Public Sub New()
End Sub
End Class
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
Public Class FakeBusiness.SomeLogic
Public Sub SomeLogic()
Dim newObject = New BusinessObject()
If newObject.IsBusinessObjectEmpty() Then
' Do something...
End If
End Sub
End Class
End Namespace
Also I read that a possible solution is to use the instructions Option Strict On/Off and also Option Infer On/Off.
I tried every possible combination between these pair of compiler instructions but it didn't work.
Anyone knows how to fix this issue with an extension method?
Another possible solution is to put the same method into a base class and implement with an interface, but I want to achieve this in this way
because it will be useful to use in every class if I use a TypeParameter in the extension method.
Any suggestion?
In a Console Application project with a root namespace of FakeBusiness, the following is the direct equivalent of that C# code:
Namespace BusinessInterface
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
End Namespace
Imports System.Runtime.CompilerServices
Imports FakeBusiness.BusinessInterface
Namespace SharedExtensions
Public Module ExtensionMethods
<Extension>
Public Function IsEmpty(theObject As IBusiness) As Boolean
Return theObject IsNot Nothing AndAlso theObject.Id <> 0
End Function
End Module
End Namespace
Imports FakeBusiness.BusinessInterface
Imports FakeBusiness.SharedExtensions
Namespace BusinessLogic
Public Class Business
Implements IBusiness
Public Property Id As Integer Implements IBusiness.Id
Public Property Name As String Implements IBusiness.Name
End Class
Module Program
Sub Main(args As String())
Dim obj As IBusiness = New Business()
Console.WriteLine($"The object is: {If(obj.IsEmpty(), "empty", "Not empty")}")
End Sub
End Module
End Namespace

The equivalent of c# virtual in vb when calling method *within* base class

I understand how to use VB's Overridable and Overrides, to get similar functionality to c#'s virtual when calling methods of a class. However, consider the c# console code below, which calls an overridden method from within the class itself:
class Program {
static void Main(string[] args) {
new test();
new test2();
Console.ReadKey();
}
}
public class test {
public test() {
hello();
}
public virtual void hello() {
Console.WriteLine("hello from base method");
}
}
class test2 : test {
public override void hello() {
Console.WriteLine("hello from overridden method");
}
}
The result I get, predictably, in c# is:
hello from base method
hello from overridden method
The problem is, I can't work out how to duplicate this functionality in VB.NET. Keep in mind here that hello() is being called from within the base class code, which runs the overridden method. That is what I can't seem to accomplish in VB.
No matter what I try in VB, the base class's hello() is always called, not the overridden hello().
Class Test:
Public Class Test
Public Sub New()
Hello()
End Sub
Public Overridable Sub Hello()
Console.WriteLine("hello from base method")
End Sub
End Class
Class Test2:
Public Class Test2
Inherits Test
Public Overrides Sub Hello()
Console.WriteLine("hello from overridden method")
End Sub
End Class
Sub Main:
Sub Main()
Dim x As New Test
Dim y As New Test2
End Sub

Using OOP in WinForms Correctly

I have 3 WinForm controls, each of which have the same functionality...
a) load data to a datagridview
b) approve data
c) run report
I want to build this with OOP in mind. I am beginning to learn OOP and to implement it into my applications.
1) Create Abstract control class that contains below abstract methods...
- LoadData()
- ApproveData()
- RunReport()
and properties...
- UserID
- PeriodRunDate
2) Create a control subclass for each of the 3 controls and implement the abstract class
3) add custom code for each of these methods
4) load these subclass controls in a Client WinForm, and call methods from client form.
Below is my code to date. Am I on the correct path? How do I use the abstract properties in the client form and subclasses?
// Abstract Class Control code...
public partial class AbstractUserControl : UserControl
{
protected abstract string userID { get; }
protected abstract string periodRunDate { get; }
protected abstract void LoadData(DoWorkEventArgs doWorkEventArgs);
protected abstract void DataLoaded(RunWorkerCompletedEventArgs runWorkerCompletedEventArgs);
protected abstract void ApproveData();
protected abstract void RunReport();
public void LoadDataButton_Click(object sender, System.EventArgs eventArgs)
{
this._uiLoadDataBackgroundWorker.RunWorkerAsync();
}
private void _uiLoadDataBackgroundWorker_DoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
this.LoadData(doWorkEventArgs);
}
private void _uiLoadDataBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
{
this.DataLoaded(runWorkerCompletedEventArgs);
}
}
// first subclass usercontrol
public partial class DetailsUserControl : UserControl
{
private DataSet.DataTable DataTable;
protected override void LoadData(DoWorkEventArgs doWorkEventArgs)
{
DataSetTableAdapters.DataTableAdapter
dataTableAdapter = new DataSetTableAdapters.DataTableAdapter();
this.DataTable = new DataSet.DataTable();
DataTableAdapter.FillData(this.DataTable, userID, periodRunDate);
}
protected override void DataLoaded(RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
{
this.bindingSource.DataSource = this.DataTable;
}
protected override void ApproveData()
{
// check each row ticked in the datagridview
// and update record in database
}
}
// Client WinForm that loads UserControl(s); Uses RunButton click event
// to call LoadButton Click in subclass controls...
private AbstractUserControl abstractUserControl;
private void RunButton_Click(object sender, EventArgs e)
{
// bind to load data button click event in abstract class
this.LoadDataButton.Click += this.abstractUserControl.LoadDataButton_Click;
}
Although the approach of having a base class that is inherited is a perfectly good one, it unfortunately does not play well with the Windows Forms designer. So if your intention is to double click the class file and then use the Form designer to drag and drop etc. then it will not work. Instead I would recommend the following alternative pattern.
Create a standard UserControl and then you can design it using the Form designer as per usual. This one control will be used for all three related scenarios you have. Then create a base class with three derived classes that implement the business logic you need.
Add a property or method to the UserControl that allows you to inject the business logic instance into the control. The control then calls the exposed abstract methods/properties of the instance. So you have a single user interface control that has a business logic instance injected to determine the essence of the processing performed.

Private or Protected Set for a MustOverride Property

I'd like to have a Private or Protected "Setter" for a property that also happens to be an abstract (MustOverride). I'm porting some code from C# to VB and in C# this is pretty straight forward. In VB not so much (for me anyway).
Some code...
In C#...
public abstract class BaseClassWithAnAbstractProperty
{
public abstract int AnAbstractIntegerProperty { get; protected set; }
}
public class Foo : BaseClassWithAnAbstractProperty
{
private int _anAbstractIntegerPropertyField = 0;
public override int AnAbstractIntegerProperty
{
get { return _anAbstractIntegerPropertyField; }
protected set { _anAbstractIntegerPropertyField = value; }
}
}
In VB...
Public MustInherit Class BaseClassWithAnAbstractProperty
Public MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
Public Class Foo
Inherits BaseClassWithAnAbstractProperty
Private _anAbstractIntegerPropertyField As Integer
Public Overrides Property AnAbstractIntegerProperty As Integer
Get
Return _anAbstractIntegerPropertyField
End Get
Protected Set(ByVal value As Integer)
_anAbstractIntegerPropertyField = value
End Set
End Property
End Class
The issue seems to be the inability to flesh-out the Get/Set specifics in the declaration.
Am I chasing a ghost?
For the record, the closest VB translation would give you:
Public MustInherit Class BaseClassWithAnAbstractProperty
Public ReadOnly MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
This might work, but as I found out, VB doesn't support this for Interfaces, at least

Constructors calling other constructors in vb.net a la c#

In c# you can have
public class Foo
{
public Foo(string name)
{
//do something
}
public Foo(string name, int bar) : this(name)
{
//do something
}
}
Is there a VB.Net equivalent?
It looks similar to Java in this respect:
Public Class Foo
Public Sub New(name As String)
' Do something '
End Sub
Public Sub New(name As String, bar As Integer)
Me.New(name)
' Do something '
End Sub
End Class
Note that you have to use MyBase.New(...) in case you want to call a constructor of a base class. See also VB.NET OOP Part2 – Understanding Constructors.