I've had problems with default properties in my code that I can - at least to some extent - reproduce with the following code:
Public Class Dawg
Public Enum DawgEnum
Demo1
Demo2
End Enum
Default Public Property DawgProp(x As DawgEnum) As String
Get
Return "whatever"
End Get
Set(value As String)
'...
End Set
End Property
Public Sub DawgSub()
Me(DawgEnum.Demo1) = "Intellisense works here..."
End Sub
End Class
Public Class DawgTest
Public Sub SomeSub()
Dim d As New Dawg
d(Dawg.DawgEnum.Demo1) = "And here as well..."
End Sub
Public Shared Sub AnotherSub()
Dim d As New Dawg
d(Dawg.DawgEnum.Demo1) = "No help for finding 'Dawg.DawgEnum.Demo1' here..."
d.DawgProp(Dawg.DawgEnum.Demo1) = "...Intellisense helped here..."
End Sub
End Class
The problem being that within the "Shared Sub AnotherSub" when I start typing "d(" Intellisense does not offer me the list of available Enum values for the property.
I also have the problem in other classes that structurally are identical to the class "DawgTest" (a simple public class) where it doesn't work either (within a shared sub or not) - although there are no problems in the test above.
Of course, this isn't a major problem since the code compiles fine and I can always use the explicit property, but it's very annoying and confusing and just like to know, if this is by-design? And, if so: why? If not: how can I fix it?
I can't for sure say, if this problem has been there all along or, if it just came up out of nowhere...
Any thoughts - even 5 cents or less - on the issue would be greatly appreciated :o)
Related
Here a sample code that produces the error. I have used MSscript in VB projects in the past and those projects are functioning.
The error reported is: "When casting from a number, the value must be a number less than infinity"
Or if anyone has another suggested way to easily add scripting to a project.
Private Sub Run_Script()
Dim scriptEngine As New MSScriptControl.ScriptControl()
Dim TestClass As New Sample
Dim ScriptCode As String
scriptEngine.Language = "VbScript"
scriptEngine.AddObject("Test", TestClass, True)
ScriptCode = "MsgBox ""tests"" "
scriptEngine.AddCode(ScriptCode)
End Sub
End Class
Public Class Sample
Public Sub Test()
MessageBox.Show("This is a test")
End Sub
End Class
I found the answer. I needed to set com visible to true. This is found under "Assembly Information"
I have created a Class Module in which I have defined a function. Whenever that function is called, it is listed twice in the locals window. Only the second one's value changes, the first one stays either empty or "zero", depending on its type, until the end of the code's execution. I don't have this problem with functions defined in standard modules. Did I do something wrong, is this a bug, or is there a logical reason behind this?
Contents of the TestClass class module:
Public Value As Double
Function AddFive() As Double
AddFive = Me.Value + 5
End Function
Contents of the standard module:
Sub TestSub()
Dim TestObject As New TestClass
TestObject.Value = 2
MsgBox TestObject.AddFive
End Sub
Here is a screenshot showing that, when the code is executed line-by-line, the function's value is listed twice in the locals window, and only the second value has changed after the function's code was executed.
(link to screenshot)
I'm using VBA for Excel 2010.
Thanks in advance.
The issue is more in how you are doing it. If you have a function that just adds 5 to an internal variable of a class object, then it's technically a void (Sub in VBA) since you don't need a return value.
Your code should be:
CLASS
Public Value As Double
Sub AddFive()
Me.Value = Me.Value + 5
End Sub
MODULE
Sub test()
Dim testObject As New TestClass
testObject.Value = 2
testObject.AddFive
MsgBox testObject.Value
End Sub
I can imagine there could be a number of reasons why there are 2 variables created, but I find it a bit pointless to go into why there is unexpected behavior since you are doing improper code.
If you want, you can even write class function that will show it's value + 5 in a msgbox and this would not create an extra variable either. But that is strange and I think you want the code above. But here it is regardless:
CLASS
Public Value As Double
Sub ShowPlusFive()
MsgBox Me.Value + 5
End Sub
MODULE
Sub test()
Dim testObject As New TestClass
testObject.Value = 2
testObject.ShowPlusFive
End Sub
How can I mock one method with RhinoMocks in VB.Net? The reference I found is in C#:
Expect.Call(delegate{list.Add(0);}).IgnoreArguments()
.Do((Action<int>)delegate(int item) {
if (item < 0) throw new ArgumentOutOfRangeException();
});
SharpDevelop converts this to:
Expect.Call(Function() Do
list.Add(0)
End Function).IgnoreArguments().Do(DirectCast(Function(item As Integer) Do
If item < 0 Then
Throw New ArgumentOutOfRangeException()
End If
End Function, Action(Of Integer)))
But that doesn't work either (it doesn't compile).
This is what I want to do: create a new object and call a method which sets some properties of that method. In real-life this method, will populate the properties with values found in the database. In test, I would like to mock this method with a custom method/delegate so that I can set the properties myself (without going to the database).
In pseudo-code, this is what I'm trying to do:
Dim _lookup As LookUp = MockRepository.GenerateMock(Of LookUp)()
_luvalue.Expect(Function(l As LookUp) l.GetLookUpByName("test")).Do(Function(l As LookUp) l.Property = "value")
Unfortunately you're attempting to do both a Sub lambda and a Statement Lambda. Neither are supported in VS2008 (but will be in the upcoming version of VS). Here is the expanded version that will work for VB
I'm guessing at the type of m_list
Class MockHelper
Dim m_list as new List(Of Object)
Public Sub New()
Expect(AddressOf CallHelper).IgnoreArguments().Do(AddressOf Do Hepler)
End Sub
Private Sub CallHelper()
m_list.Add(0)
End Sub
Private Sub DoHelper(ByVal item as Integer)
if item < 0 Then
Throw New ArgumentOutOfRangeException
End If
End Sub
End Class
I have never mocked something w/ both a delegate and a lambda so I can't give a full solution to this problem, but I did want to share some example code for the usual "AssertWasCalled" function in Rhino Mocks 3.5 for vb developers because I spent some time trying to grok this... (keep in mind the below is kept simple for brevity)
This is the method under test - might be found inside a service class for the user object
Public Sub DeleteUserByID(ByVal id As Integer) Implements Interfaces.IUserService.DeleteUserByID
mRepository.DeleteUserByID(id)
End Sub
This is the interactive test to assert the repository method gets called
<TestMethod()> _
Public Sub Should_Call_Into_Repository_For_DeleteProjectById()
Dim Repository As IUserRepository = MockRepository.GenerateStub(Of IUserRepository)()
Dim Service As IUserService = New UserService(Repository)
Service.DeleteUserByID(Nothing)
Repository.AssertWasCalled(Function(x) Wrap_DeleteUserByID(x))
End Sub
This is the wrap function used to ensure this works w/ vb
Function Wrap_DeleteUserByID(ByVal Repository As IUserRepository) As Object
Repository.DeleteUserByID(Nothing)
Return Nothing
End Function
I found this to be a very nasty solution, but if it helps someone w/ the same issues I had it was worth the time it took to post this ;)
I am a vb.net newbie, so please bear with me. Is it possible to create properties (or attributes) for a class in visual basic (I am using Visual Basic 2005) ? All web searches for metaprogramming led me nowhere. Here is an example to clarify what I mean.
public class GenericProps
public sub new()
' ???
end sub
public sub addProp(byval propname as string)
' ???
end sub
end class
sub main()
dim gp as GenericProps = New GenericProps()
gp.addProp("foo")
gp.foo = "Bar" ' we can assume the type of the property as string for now
console.writeln("New property = " & gp.foo)
end sub
So is it possible to define the function addProp ?
Thanks!
Amit
It's not possible to modify a class at runtime with new properties1. VB.Net is a static language in the sense that it cannot modify it's defined classes at runtime. You can simulate what you're looking for though with a property bag.
Class Foo
Private _map as New Dictionary(Of String, Object)
Public Sub AddProperty(name as String, value as Object)
_map(name) = value
End Sub
Public Function GetProperty(name as String) as Object
return _map(name)
End Function
End Class
It doesn't allow direct access in the form of myFoo.Bar but you can call myFoo.GetProperty("Bar").
1 I believe it may be possible with the profiling APIs but it's likely not what you're looking for.
Came across this wondering the same thing for Visual Basic 2008.
The property bag will do me for now until I can migrate to Visual Basic 2010:
http://blogs.msdn.com/vbteam/archive/2010/01/20/fun-with-dynamic-objects-doug-rothaus.aspx
No - that's not possible. You'd need a Ruby like "method_missing" to handle the unknown .Foo call. I believe C# 4 promises to offer something along these lines.
I normally use C# and I'm attempting to convert a qbasic programmer to the joys of object oriented programming by easing him into VB 2005.
Below is a extremely simplified version of what I'm trying to accomplish. It successfully compiles, but all members in the array of card objects are set to "Nothing". The test line throws a NullReferenceException. What am I doing wrong?
Sub Main()
Dim deck1 As New Deck
Console.WriteLine("Test: " & deck1.cards(2).face)
End Sub
Class Card
Public face As String
Sub New()
face = "Blank"
End Sub
End Class
Class Deck
Public cards(51) As Card
End Class
Yes, when you create an array in .NET, every element of the array is set to the default value of the element type - which is null/Nothing for classes.
You need to populate the array before you use it (or expect it to be full of null references).
Note that this would have behaved exactly the same way in C#.
EDIT: As no-one's actually posted population code that would work yet, here it is:
Class Deck
Public cards(51) As Card
Public Sub New()
For i As Integer = 0 To cards.Length-1
cards(i) = New Card()
Next
End Sub
End Class
You need to do some sort of
For Each currentItem As String in Me.face
currentItem = "Blank"
End
Apologies if the syntax of the for-each is off, I'm a C# guy normally. But the basic issue is that you haven't initialized each element of the array.