ok I do have class like this.
Namespace mySpace
Public Class ClassA
Private Function MethodA(prm AS Boolean) As Boolean
Return False
End Function
Private Function MethodB() As Boolean
Return False
End Function
End Class
Public Class ClassB
Private Function MethodC() As Boolean
Return True
End Function
Private Function InvokeA() As Boolean
Dim methodObj As MethodInfo
'null pointer except below here
methodObj = Type.GetType("mySpace.ClassA").GetMethod("MethodA")
Dim params As Boolean() = {False}
Return CBool(methodObj.Invoke(New ClassA(), params))
End Function
End Class
End Namespace
What I am trying here is to invoke a method from a different class with parameters using its method. But this returns a null pointer exception. Why? Where I went wrong?
You are doing various things wrong. The following code should work without any problem:
Dim objA As ClassA = New ClassA()
methodObj = objA.GetType().GetMethod("MethodA", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim params As Object() = {False}
methodObj.Invoke(objA, params)
You have various errors which shouldn't allow your code to run at all, namely:
You are retrieving a private method without the adequate
BindingFlags.
You are not passing the arguments as Object type.
Additionally, you are not using GetMethod with an instantiated object of ClassA (e.g., objA above) and instance.GetType(); I am not 100% sure that you need to do that (perhaps you can accomplish it as you intend), but performing this step is a pretty quick process and would allow the code above to work without any problem.
Related
I'm trying to pass an optional callback parameter to my class when I instantiate it. I need a callback method to format some value that may or may not need formatting.
Here is my simplified code of what I am trying to do:
Public Class ColumnSpec
Property Title As String
Property Name As String
Property Value As String
Delegate Function CallBack(aValue As String) As String
Property HasCallBack As Boolean
Public Sub New(aTitle As String, aName As String, Optional aCallBack As CallBack = Nothing)
_Title = aTitle
_Name = aName
' How do I assign aCallBack to the delegate function here?
_HasCallBack = aCallBack IsNot Nothing
End Sub
End Class
I may or may not pass a callback function when instantiating ColumnSpec.
In another class, I need to check and call the delegate.
Public Class MyClass
Public Function FormatText(Value as String) As String
Return Value + "01234" ' Return value after modifying
End Function
Public Function RenderValue() As String
Dim lNewCol1 as ColumnSpec("Title1", "Name2", AddressOf FormatText)
Dim lNewCol2 as ColumnSpec("Title2", "Name2")
' How do I check if there is a delegate and call it?
If lNewCol1.HasCallBack Then lNewCol1.Value = lNewCol1.CallBack(lNewCol1.HasCallBack)
If lNewCol2.HasCallBack Then lNewCol2.Value = lNewCol1.CallBack(lNewCol2.HasCallBack)
End Function
End Class
I am completely new to delegates. Any ideas on how I can solve this?
Your line Delegate Function CallBack(aValue As String) As String only declares the type of the callback. You need a separate property or field to hold the reference.
So, you would modify the class slightly:
Delegate Function CallbackFunction(aValue As String) As String
Public ReadOnly Property Callback As CallbackFunction
Public ReadOnly Property HasCallback As Boolean
Get
'Alternatively, you could assign the value in the ctor as in your code...
Return Callback IsNot Nothing
End Get
End Property
Public Sub New(Optional aCallback As CallbackFunction = Nothing)
Me.Callback = aCallback
End Sub
Your client code is fine as-is and doesn't need to be changed.
If you don't care about having a named type for the callback function, you could also use newer syntax, e.g.
Public ReadOnly Property Callback As Func(Of String, String)
Also modifying the constructor accordingly.
The client code would still work fine as-is with this modification.
(Action is to Sub as Func is to Function.)
So basically what I want to do is to store a reference to a boolean value in my class.
It looks something like this:
Public Class TestClass
Private boolRef As Boolean
Public Sub New(ByRef inBoolRef As Boolean)
boolRef = inBoolRef 'Assign reference of "inBoolRef" to "boolRef"
End Sub
Public Sub changeBool()
boolRef = true 'Change value of the referenced boolean variable (outside of this class)
End Sub
End Class
The object of that class is running in a parallel thread, and that's why I want the object to control the variable in its own thread.
And with my program doing this:
Module Program
Dim myBool As Boolean = false
Sub Main(args As String())
Dim tC As New TestClass(myBool)
'Opens a parallel thread in which the object does things
'and should change "myBool" to true when the object is terminated
End Sub
End Module
What I don't get is, that I declare a Boolean variable. Then I want another, in my Class saved variable to reference that variable (which was input in the ctor).
In boolRef = inBoolRef I handle boolRef as if it was an actual reference.
But in boolRef = true in changeBool() it seems as if it's not a reference anymore.
This question shows me, that it is possible in VB.Net and also works, at least with objects.
But I can't assign different values to the myBool through means of the other instantiated object, which should store a reference to the variable. I mean, I could theoretically do something in the class like
Public Sub changeBool()
boolRef.doSomethingLikeAssignAValue()
End Sub
but that won't work, because as far as I know, the Boolean is a primitive data type, and thus can not be changed by any Subs.
I come from the C(++) world and there I find it way more intuitive on how to handle references, pointers, etc.
TL;DR:
What I wan't to do is basically this (in C(++)):
Class BoolChanger
{
Private:
bool *boolRef = nullptr;
Public:
inline BoolChanger(bool *inBoolRef)
{
boolRef = inBoolRef;
}
inline void change()
{
*boolRef = true; // Change value of pointed-to boolean variable
}
}
int main(int argc, char *argv[])
{
bool myBool = false;
// Open parallel thread in which the object runs an does its things
BoolChanger bc(&myBool);
// ... and when it's done, it should set myBool to "true"
return 0;
}
but in VB.Net. Please can someone help me? I seem to be missing something which is important to know...
You can simply pass the parameter to the method directly instead of trying to assign it to a Boolean value first. Like this:
Public Class TestClass
Private boolRef As Boolean
Public Sub New()
End Sub
Public Sub changeBool(ByRef inBoolRef As Boolean)
inBoolRef = true
End Sub
End Class
Then use I like this
Module Program
Dim myBool As Boolean = false
Sub Main(args As String())
Dim tC As New TestClass
tC.changeBool(myBool)
End Sub
End Module
I don't know if there was a reason you didn't do it this way previously. Please let me know if your program does not support this way :)
I am in the process of converting some c# code to vb.net and I keep running into an issue with a particular method.
Here is the c# method signature -
public void DoSomething(Action<T> something)
{ .... do something in here }
Here is my vb.net conversion of the signature -
Public Sub DoSomething(ByVal something As Action(Of T))
....do something in here
End Sub
I have to call this with a variable. Here is a sample c# call -
_myobject.DoSomething(x => { newValue = x.CallSomeMethod() });
How would I perform this same call using Vb.Net?
I've tried this (along with a few variations), but the newValue object is always empty -
_myObject.DoSomething(Sub(x) newValue = x.CallSomeMethod())
I've also tried this -
_myObject.DoSomething(Function(x) newValue = x.CallSomeMethod() End Function)
If I do this -
_myObject.DoSomething(Function(x) newValue = x.CallSomeMethod())
I get an error message stating Cannot apply operator '=' to operands of type myType and myType
The SourceClass has the DoSomething method and the TargetClass has the CallSomeMethod that will be called as part of the anonymous Sub:
Public Class SourceClass
Public Sub DoSomething(ByRef something As Action(Of TargetClass))
Dim t As New TargetClass
something(t)
End Sub
End Class
Public Class TargetClass
Function CallSomeMethod() As Integer
Return 1000
End Function
End Class
In the Main method add this:
Public Module Module1
Sub Main()
Dim newValue = 11
Dim myObject = New SourceClass
myObject.DoSomething(New Action(Of TargetClass)(Sub(obj) newValue = obj.CallSomeMethod()))
Debug.WriteLine(newValue)
End Sub
End Module
In this example newValue will be assigned 1000.
I'm doing some LINQ which requires a custom comparer, so I created a new class implementing IEqualityComparer. However, when I use it, I have to create an instance of it each time.
Dim oldListOnly = oldList.Except(newList, New MyEqualityComparer)
Dim newListOnly = newList.Except(oldList, New MyEqualityComparer)
I may be misunderstanding how .NET works, but it seems wasteful to create a new comparer each time. I really just want one instance (the equivalent of static in C++/C#).
So I tried creating a "static" class, which in vb.net is a module. But got an 'Implements' not valid in Modules error.
I then tried making the Equals and GetHashCode function shared methods on my class, but got this error: Methods that implement interface members cannot be declared 'Shared'.
Any ideas how to accomplish my goal here? Or am I simply misunderstanding what's going behind the scenes?
Your understanding is correct, although the waste is unlikely to be noticeable. For your situation, you could use the singleton pattern, which usually goes something like this:
Public Class MyEqualityComparer
Implements IEqualityComparer(Of whatever)
Private Sub New()
'no outsider creation
End Sub
Private Shared ReadOnly _instance As New MyEqualityComparer()
Public Shared ReadOnly Property Instance As MyEqualityComparer
Get
Return _instance
End Get
End Property
'other code
End Class
Why not simply do
Dim comparer = New MyEqualityComparer
Dim oldListOnly = oldList.Except(newList, comparer )
Dim newListOnly = newList.Except(oldList, comparer )
There needs to be an instance of a concrete type that implements IEqualityComparer. What you can do with a module, however, is define a public instance which is initialized to "New EqualityComparer". You can then pass that default instance to the Except method.
Something like:
Public Module MyComparer
Public acmeComparer As acmeCompareType
Public Class acmeCompareType
Implements IEqualityComparer(Of System.Drawing.Point)
Public Function Equals1(x As System.Drawing.Point, y As System.Drawing.Point) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of System.Drawing.Point).Equals
Return Math.Abs(x.X) = Math.Abs(y.X) AndAlso Math.Abs(x.Y) = Math.Abs(y.Y)
End Function
Public Function GetHashCode1(obj As System.Drawing.Point) As Integer Implements System.Collections.Generic.IEqualityComparer(Of System.Drawing.Point).GetHashCode
' Note that obj is a struct passed by value, so we can safely modify it here
' (without affecting the caller's instance)
obj.X = Math.Abs(obj.X)
obj.Y = Math.Abs(obj.Y)
Return obj.GetHashCode
End Function
End Class
End Module
I am converting DataTables to a generic list and need a quick and easy way to implement a Find function. It seems I am going to have to use a Predicate. Upon further investigation, I still can't seem to re-create the functionality. I have this predicate...
Private Function ByKey(ByVal Instance As MyClass) As Boolean
Return Instance.Key = "I NEED THIS COMPARISON TO BE DYNAMIC!"
End Function
And then calling it like this...
Dim Blah As MyClass = MyList.Find(AddressOf ByKey)
But I have no way to pass in a key variable to this predicate to do the comparison, as I used to do with DataTable...
Dim MyRow as DataRow = MyTable.Rows.Find(KeyVariable)
How can I setup a predicate delegate function in VB.NET to accomplish this?
Do not recommend LINQ or lambdas because this is question is regarding .NET version 2.0.
Just put your predicate in a class instance:
Public Class KeyMatcher
Public Sub New(ByVal KeyToMatch As String)
Me.KeyToMatch = KeyToMatch
End Sub
Private KeyToMatch As String
Public Function Predicate(ByVal Instance As MyClass) As Boolean
Return Instance.Key = KeyToMatch
End Function
End Class
and then:
Dim Blah As MyClass = MyList.Find(AddressOf New KeyMatcher("testKey").Predicate)
We can even get a little fancy and make this generic:
Public Interface IKeyed(Of KeyType)
Public Key As KeyType
End Interface
Public Class KeyMatcher(Of KeyType)
Public Sub New(ByVal KeyToMatch As KeyType)
Me.KeyToMatch = KeyToMatch
End Sub
Private KeyToMatch As KeyType
Public Function Predicate(ByVal Instance As IKeyed(Of KeyType)) As Boolean
Return Instance.Key = KeyToMatch
End Function
End Class
And then make your MyClass type implement the new IKeyed interface