Tag Archives: vb.net

Simple Screen Shot of all Multiple Monitors

Don’t you love it when you take a heaping mess of code and simplify it to it’s essence. It’s even better when you find code in libraries that you can use and delete your own. The less code you own the better. I went searching for a simple code sample to take a screen shot of all screens regardless of the configuration of the monitors. I couldn’t find anything small and easy. by the time I got done figuring it out I thought it should be out on the interwebs just to make it easier for the next guy.  Here it is:

Imports System.Drawing
Imports System.Windows.Forms
Imports System.Drawing.Imaging
Imports System.Windows.SystemParameters

Public Class ScreenHelper
    Shared Sub SaveAllScreens(ByVal FileName As String)

        Using bmp As New Bitmap(VirtualScreenWidth, VirtualScreenHeight, Imaging.PixelFormat.Format32bppArgb)
            Using gr As Graphics = Graphics.FromImage(bmp)
                gr.CopyFromScreen(VirtualScreenLeft, VirtualScreenTop, 0, 0, bmp.Size)
                bmp.Save(FileName)
            End Using
        End Using

    End Sub
End Class

That looks nice and easy. You will need references to System.Drawing and System.Windows.Forms if you are using WPF. This works even in the primary window is to the right of any other monitors making the area of the capture be negative. Hopefully this will help someone. Let me know if you have any suggestions.

Updateable Fluent Collection

In my previous posts about my Adventures in Creating Fluent Interfaces I created a way to fluently filter objects in a collection by the methods of the object. That’s all nice and dandy but what is it worth if you can’t manipulate the objects in the same way. I want to be able to change the object also. My first goal is to just manipulate the properties on the object and not yet children objects. When I began I just started with an ‘Update’ method on the FluentComparableList object which was the object I returned when I selected PeopleList.Name which gave me all the filtering methods like greater and contains.

The Design Problem – invalid options

While writing out my tests (Not quite TDD but I did them really soon) I realized that this created issues. If I had a read only property I didn’t want the Set method to appear in the list because It would not work. I it’s a write only parameter then I didn’t want all the filtering methods available because there is no data to filter on. I noticed this when I wrote People.Name.IndexOf(“e”)… the ‘Set’ option came up. What would that be setting. I can’t set the index of the letter ‘e’! Am I setting the name before it? It’s unclear syntax. I decided I needed a separate object for updating than filtering.

First Solution – differentiate by additional options

This posed another issue because there are many cases where a method can both be updated and filtered. If it can be written to and read from I should be able to Update and Filter it. You can’t inherit from two objects (not in VB at least) so I had a quandary. I built out an example where I chose which to do in the syntax. For example: PeopleList.Name.Filter.Contains(“e”) but that lengthened the syntax. No, there had to be a better way.

Second Solution – Composition objects

My current solution is to create one object for update and another object for filtering and a third object that composes these together. It is a lot of complicated code but, once again, this code is in a library and should not change often. That is where the complexity can be managed. There is probably something better. I look forward to your suggestions.

When I type PersonList.Name I will receive a special string collection I call FluentStringCollection that has all the update and filter methods. When I type Personlist.Name.indexof(‘e’) I don’t have to return a collection that has all the update methods. i can just return a collection with just the filter methods. Separating it out also makes the code easier to follow and helps get closer to the single responsibility principal.

The Code

To get this done we will need more classes. I have the FluentComparableList from the last post but I renamed it to FluentCollectionFilter. I’m constantly trying to have the name make the most sense until I come to a release point. It remains mostly unchanged. Here it is so you can see where the other classes fit in.

Public Class FluentCollectionFilter(Of CollectionType As {ICollection, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As CollectionType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean

    Sub New(ByRef list As CollectionType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New CollectionType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal value As ParamaterType) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(value) > 0)
    End Function

    Public Function Lesser(ByVal value As ParamaterType) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(value) < 0)
    End Function

    Public Function LesserOrEqual(ByVal value As ParamaterType) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(value) <= 0)
    End Function

    Public Function GreaterOrEqual(ByVal value As ParamaterType) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(value) >= 0)
    End Function

    Public Function Between(ByVal Min As ParamaterType, ByVal Max As ParamaterType) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(Min) >= 0 And InternalFunction(item).CompareTo(Min) <= 0)
    End Function

    Public Shadows Function Equals(ByVal value As ParamaterType) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).Equals(value))
    End Function

End Class

To that we add our FluentCollectionSetter. You guessed it, this is the class that has all the methods for updating the objects in a collection. Right now there is only one which is Set. I’m still playing with the names. ‘Set’ is shorter than ‘Update’ but it is a reserved word. You will notice that there is also a new function InternalSetter. This is where we pass in the a function to update the parameter. A function to read a parameter is significantly different from a function to write so I needed to pass in a pointer to what function updates the proper parameter. More on that later.

Public Delegate Sub Setter(Of ItemType, ParamaterType)(ByRef item As ItemType, ByVal value As ParamaterType)

Public Class FluentCollectionSet(Of CollectionType As {ICollection, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As CollectionType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public InternalSetter As Setter(Of ItemType, ParamaterType)


    Sub New(ByRef list As CollectionType, ByVal _Func As Func(Of ItemType, ParamaterType), ByRef _Setter As Setter(Of ItemType, ParamaterType))
        InternalList = list
        InternalFunction = _Func
        InternalSetter = _Setter
    End Sub

    Function [Set](ByVal Value As ParamaterType) As CollectionType
        For Each item In InternalList
            InternalSetter(item, Value)
        Next
        Return InternalList
    End Function
End Class

Now we need a third class that combines the FluentCollectionFilter and the FluentCollectionSetter. I could not inherit from two objects so I composed them together by setting up every method and wiring up the calls. Usually you could just inherit the methods and your class is much more concise. Here is the combined class:

Public Class FluentCollection(Of CollectionType As {ICollection, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As CollectionType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean
    Public InternalSetter As Setter(Of ItemType, ParamaterType)

    Sub New(ByRef list As CollectionType, ByVal _Func As Func(Of ItemType, ParamaterType), ByRef _Setter As Setter(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        InternalSetter = _Setter
        useNot = _Not
    End Sub

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        GetNewList(_Func)
    End Function


    Public Function [Set](ByVal value As ParamaterType) As CollectionType
        Return New FluentCollectionSet(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, InternalSetter). _
        Set(value)
    End Function

    Public Function Greater(ByVal value As ParamaterType) As CollectionType
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        Greater(value)
    End Function

    Public Function Lesser(ByVal value As ParamaterType) As CollectionType
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        Lesser(value)
    End Function

    Public Function LesserOrEqual(ByVal value As ParamaterType) As CollectionType
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        LesserOrEqual(value)
    End Function

    Public Function GreaterOrEqual(ByVal value As ParamaterType) As CollectionType
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        GreaterOrEqual(value)
    End Function

    Public Function Between(ByVal Min As ParamaterType, ByVal Max As ParamaterType) As CollectionType
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        Between(Min, Max)
    End Function

    Public Shadows Function Equals(ByVal value As ParamaterType) As CollectionType
        Return New FluentCollectionFilter(Of CollectionType, ItemType, ParamaterType)(InternalList, InternalFunction, useNot). _
        Equals(value)
    End Function
End Class

One More class to inherit from the FluentCollection above to add on the special String only filter and updates. I just inherited as it works for what I am doing now and is significantly concise.

Public Class FluentCollectionString(Of CollectionType As {ICollection, New}, ItemType)
    Inherits FluentCollection(Of CollectionType, ItemType, String)

    Sub New(ByRef list As CollectionType, ByVal _Func As Func(Of ItemType, String), ByRef _Setter As Setter(Of ItemType, String), Optional ByVal _Not As Boolean = False)
        MyBase.New(list, _Func, _Setter, _Not)
    End Sub

    Public Shadows Function [Not]() As FluentCollectionString(Of CollectionType, ItemType)
        Return New FluentCollectionString(Of CollectionType, ItemType) _
        (InternalList, Function(s) InternalFunction(s), InternalSetter, True)
    End Function

    Public Function StartsWith(ByVal value As String) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).StartsWith(value))
    End Function

    Public Function EndsWith(ByVal value As String) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).EndsWith(value))
    End Function

    Public Function Contains(ByVal value As String) As CollectionType
        Return GetNewList(Function(item) InternalFunction(item).Contains(value))
    End Function

    Public Function IndexOf(ByVal value As String) As FluentCollectionFilter(Of CollectionType, ItemType, Integer)
        Return New FluentCollectionFilter(Of CollectionType, ItemType, Integer) _
        (InternalList, Function(s) InternalFunction(s).IndexOf(value))
    End Function

    Public Function Replace(ByVal oldValue As String, ByVal newValue As String) As CollectionType
        For Each item In InternalList
            Me.InternalSetter(item, InternalFunction(item).Replace(oldValue, newValue))
        Next
        Return InternalList
    End Function

As it turns out I could not figure out how to update items inside a function statement or a lambda. I tried several options including setting everything to ByRef but there is no ByRef on the function itself. The MSDN documentation implies that both of these are always read only. To be able to modify an item in a function I create a delegate and set it to the address of a function that sets the parameter. This adds several lines of code to each Parameter which you will see below. You will see that in the code below for the implementation of the new PersonList Class. This code is different from above in that it is not in the Fluent library. This is what your code would look like when using the library. It could be generated though as it is mostly just hooking things up.

Public Class PersonList
    Inherits List(Of Person)

    Sub New()
        MyBase.new()
    End Sub

    Sub New(ByVal List As List(Of Person))
        MyBase.New(List)
    End Sub

    Public Function Name() As FluentCollectionString(Of PersonList, Person)
        Return New FluentCollectionString(Of PersonList, Person)(Me, Function(s) s.Name, AddressOf NameSetter)
    End Function

    Private Sub NameSetter(ByRef si As Person, ByVal value As String)
        si.Name = value
    End Sub

    Public Function BirthDate() As FluentCollection(Of PersonList, Person, Date)
        Return New FluentCollection(Of PersonList, Person, Date) _
        (Me, Function(s) s.BirthDate, AddressOf BirthDateSetter)
    End Function

    Public Function BirthDate(ByVal value As Date) As PersonList
        Return New FluentCollection(Of PersonList, Person, Date) _
        (Me, Function(s) s.BirthDate, AddressOf BirthDateSetter). _
        Set(value)
    End Function

    Private Sub BirthDateSetter(ByRef si As Person, ByVal value As String)
        si.BirthDate = value
    End Sub
End Class

It’s starting to get quite complicated but if it can be code generated then it won’t be too bad. If it could be generated then you could just build your Person class and generate the collection to use the library and voila! lots of power with little work. The FluentCollectionString might also be generated and not be in the library. I’ll have to think about that more.

Now we can update our collected objects in the same line we filter them. We could change all the letter ‘e’ to the letter ‘a’ in everyone’s name borne after 1980 with just:

People.BirthDate.Greater(“1/1/1980”).Name.Replace(‘e’,’a’)

Now that’s power! Tell me what you think.

Fluent Collection NOT !

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

The title of this post might be a little misleading. I am still having Adventures in Creating Fluent Interfaces. I wanted to be able to find People with Names that did NOT Contain some text. I started of by adding a new function NotContains but I quickly realized that I would be doubling my functions. The answer was so simple and felt so good. I had already centralized by code that evaluated the function so I just needed to add an optional parameter boolean for tracking if I wanted the standard function or the ‘Not’ version. I added a variable to hold it. I modified the GetList function to use the new variable. Finally I created a new “Not’ function that returns the same FluentComparableList but passes in the boolean as true. Here is the modified FluentComparableList code sample:

 

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)
    Public useNot As Boolean


    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType), Optional ByVal _Not As Boolean = False)
        InternalList = list
        InternalFunction = _Func
        useNot = _Not
    End Sub

    Public Function [Not]() As FluentComparableList(Of ListType, ItemType, ParamaterType)
        Return New FluentComparableList(Of ListType, ItemType, ParamaterType)(InternalList, Function(s) InternalFunction(s), True)
    End Function

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If useNot Then
                If Not _Func(item) Then GetNewList.Add(item)
            Else
                If _Func(item) Then GetNewList.Add(item)
            End If
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc..

I do even fewer changes to the FluentStringList. I just pass the boolean on to the base class. I have to shadow the Not class in the base class because I want to return a FluentStringList instead of the FluentStringList that comes out of the base. Now I have the ability to ‘Not’ everything. I can find out how many people don’t have ‘tle’ in their name with:

People.Name.Not.Contains('tle').count

Here are some tests:

Dim target As PersonList

Public Sub MyTestInitialize()
    target = New PersonList
    target.Add(New Person("Bentley", "1/1/1973"))
    target.Add(New Person("Joe", "2/1/1992"))
    target.Add(New Person("Jimmy", "3/1/2005"))
    target.Add(New Person("Karla", "4/1/1984"))
    target.Add(New Person("Cameron", "5/1/1950"))
End Sub


Public Sub FindAll_not_StartsWith()
    Dim Found = target.Name.Not.StartsWith("J")

    Assert.AreEqual(3, Found.Count)
    Assert.AreEqual(5, target.Count, "Has no side-effects")
End Sub


Public Sub BigTest()
    Dim Found = target.Name.Not.EndsWith("y").Name.Not.IndexOf("e").Not.Greater(1)

    Assert.AreEqual(1, Found.Count)
    'Only Karla should match this one
End Sub

I wouldn’t suggest using that many ‘Not’s in production code. It’s amazing how much power we got from so little code. Tell me what you think of this modification in the comments below.

Fluent iComparable for Everyone

I was working on my Fluent Helper class and I wanted to add a BirthDate field to my example person class. I wanted to be able to filter item if they were Greater or Less than a date. I then realized that I also wanted that for my String class. The String and Date types both support the iComparable interface. Most types do. If I made a generic class using icomparable then I could use that for Date and use it as a base class for Strings. Here is the new class FluentComparableList that can be a base for most other types:

Public Class FluentComparableList(Of ListType As {IList, New}, ItemType, ParamaterType As IComparable)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, ParamaterType)

    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, ParamaterType))
        InternalList = list
        InternalFunction = _Func
    End Sub

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
             If _Func(item) Then GetNewList.Add(item)
        Next
    End Function

    Public Function Greater(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) > 0)
    End Function

    Public Function Lesser(ByVal i As Integer) As ListType
        Return GetNewList(Function(item) InternalFunction(item).CompareTo(i) < 0)
    End Function
etc...

When I refactored the StringWhere class I renamed it FluentStringList and ended up with:

Public Class FluentStringList(Of ListType As {IList, New}, ItemType)
    Inherits FluentComparableList(Of ListType, ItemType, String)

    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, String))
        MyBase.New(list, _Func, _Not)
        InternalList = list
        InternalFunction = _Func
    End Sub

    Public Function StartsWith(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).StartsWith(value))
    End Function

    Public Function EndsWith(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).EndsWith(value))
    End Function

    Public Function Contains(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).Contains(value))
    End Function

    Public Function IndexOf(ByVal value As String) As FluentComparableList(Of ListType, ItemType, Integer)
        Return New FluentComparableList(Of ListType, ItemType, Integer)(InternalList, Function(s) InternalFunction(s).IndexOf(value))
    End Function

End Class

You also see a new function on the FluentStringList class called IndexOf. Yes, that is the collection version of the string function IndexOF which tells you the placement of one text string in another. Since it uses the FluentComparableList I can use the integer from the IndexOf and check if it is greater than or less than another integer. For example, Let’s say i want to count all the people with names where the letter ‘e’ was in the name but it was further than the 2nd character from the beginning. It would be as simple as:

People.Name.IndexOf("e").Greater(2).count

Now that was fun! I almost forgot about the BirthDate Field. Here is the Person and the People classes with it implemented:

Public Class Person
    Public Name As String
    Public BirthDate As Date

    Sub New(ByVal _Name As String, ByVal _BirtDate As Date)
        Name = _Name
        BirthDate = _BirtDate
    End Sub

End Class


Public Class PersonList
    Inherits List(Of Person)

    Sub New()
        MyBase.new()
    End Sub

    Sub New(ByVal List As List(Of Person))
        MyBase.New(List)
    End Sub

    Public Function Name() As FluentStringList(Of PersonList, Person)
        Return New FluentStringList(Of PersonList, Person)(Me, Function(s) s.Name)
    End Function

    Public Function BirthDate() As FluentComparableList(Of PersonList, Person, Date)
        Return New FluentComparableList(Of PersonList, Person, Date)(Me, Function(s) s.BirthDate)
    End Function

End Class

Now to see how many people were borne since 1973 I can:

People = New PersonList
People.Add(New Person("Bentley", "1/1/1973"))
People.Add(New Person("Joe", "2/1/1992"))
People.Add(New Person("Jimmy", "3/1/2005"))
People.Add(New Person("Karla", "4/1/1984"))
People.Add(New Person("Cameron", "5/1/1950"))

Debug.Print People.BirthDate.Greater("12/31/1972")
'Prints 4 (only Cameron was borne before 12/31/1972)

I would like to hear what you think in the comments below. Please don’t frustrate, educate!

Adventures in Creating Fluent Interfaces V2

I looked at the code and it looked at the code from my last Adventures in Creating Fluent Interfaces and it looked convoluted and clunky. I also realized that I was creating a copy of most of the objects and more objects with every dot in my syntax. There had to be another way.  I realized that if I could just pass the method I wanted to evaluate (the innerText method in this case) then I could just pass down the original list to the next object in the chain then perform the selection function on it (like the “Contains” function) and if it returned true then I could include that in the next collection. I created lamdas and passed them down in the constructor for the object with the original list and boy does that look better.

To simplify the example I used the canonical Person class that just holds one name. We will add more later.

Public Class Person
    Public Name As String

    Sub New(ByVal _Name As String)
        Name = _Name
    End Sub

End Class

From there we want to get to this code:

People = New PersonList
People.Add(New Person("Bentley"))
People.Add(New Person("Joe"))
People.Add(New Person("Jimmy"))
People.Add(New Person("Karla"))
People.Add(New Person("Cameron"))

Debug.Print People.Name.StartsWith("J").count
'Prints 2 (for Joe and Jimmy)

Debug.Print People.Name.StartsWith("J").Name.EndsWith("y").count
'Prints 1 (for Jimmy)

That looks great! Now how do we get there. First, we want a collection of people.

Public Class PersonList
    Inherits List(Of Person)

    Sub New()
        MyBase.new()
    End Sub

    Sub New(ByVal List As List(Of Person))
        MyBase.New(List)
    End Sub

    Public Function Name() As StringWhere(Of PersonList, Person)
        Return New StringWhere(Of PersonList, Person)(Me, Function(s) s.Name)
    End Function

End Class

So when we call ‘People.Name’ we receive a StringWhere object. That is a generic class that we don’t have to write each time. Here is the beginning of it to give you an idea

Public Class StringWhere(Of ListType As {IList, New}, ItemType)
    Public InternalList As ListType
    Public InternalFunction As Func(Of ItemType, String)

    Sub New(ByRef list As ListType, ByVal _Func As Func(Of ItemType, String))
        InternalList = list
        InternalFunction = _Func
    End Sub

    Public Function GetNewList(ByRef _Func As Func(Of ItemType, Boolean))
        GetNewList = New ListType
        For Each item In InternalList
            If _Func(item) Then GetNewList.Add(item)
        Next
    End Function

    Public Function StartsWith(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).StartsWith(value))
    End Function

    Public Function Contains(ByVal value As String) As ListType
        Return GetNewList(Function(item) InternalFunction(item).Contains(value))
    End Function
etc...

Now we can iterate over it as many times as we want using StartsWith or EndsWith or Contains and filter what we need. We can add other text fields like LastName or StreetAddress and do the same with them by just also adding it to the collection like we did with the Name field. Now you can easily find the objects you want and look good doing it. Let me know if you have any other ideas or see any disadvantages in this approach or even the whole concept. Please don’t frustrate, educate!

Adventures in Creating Fluent Interfaces

I have been listening to lots of podcasts about programming languages and I find it fascinating. I am trying to be more of a craftsman. As I write code in my job or personal time I ask myself if it is concise and legible. I was working on some software tools to read and manipulate websites programmatically. I found myself writing a lot of code to find a field on the page that matches certain criteria then taking action on the field. I took the opportunity to explore what could be done. I did this before researching a lot so I could discover it myself. Later I compared my work with others.

For example, I had a web page where I needed to click on a specific link. The anchor tag had no ID or Name associated to it so I had to search through all the anchor tags with a specific inner HTML. This looks like:

MyDocument = WebBrowser.Document
MyElements = MyDocument.getElementsByTagName(TagName)
For n = 0 To MyElements.length - 1
    MyElement = MyElements(n)
    If InStr(MyElement.innerHTML, InnerHTML) Then
        ReturnElements.Add(MyElement)
    End If
Next
Dim MyElement As IHTMLElement = ReturnElements(0)
If Not MyElement Is Nothing Then MyElement.click()

That’s not ideal code but you get the point. I wrote this while I was iterating through so I didn’t optimize it. Since i was doing it a lot I made a function that did it all and added it an as extension method to the Web Browser class. It’s use looked like:

webbrowser.ClickByInnerHTMLContainsAndWait("a", "By Channel")

That looked concise but I quickly had other needs and ended up with other extensions like GetElementsIfOuterHTMLContains and GetElementsIfInnerTextContains which resulted in an explosion of methods. It was easy to read but had a complex structure and was difficult to maintain. I decided I wanted a more flexible syntax. Taking a step back I decided to write out what I wanted to say and then I could see if I could bend the language to do it my way. Here is what I wanted:

'In all the text fields on the web page that contain the word 'Bentley' replace it with 'Smart'
WebBrowser.textfields.replace("Bentley", "Smart")
'This will Click the 'Next" link
WebBrowser.links.innertext.contains("Next").first.click
'You can even chain things together
'Click the last link on the web page that begins with 'St' and ends with 'x'
WebBrowser.links.innerText.beginsWith("St").innerTest.EndsWith("x").last.click

That would be great. How could I do that? It could be done with linq.

elements.Where(Function(s) s.innerText.StartsWith("St")).Where(Function(s) s.innerText.EndsWith("x")).Last.click

That works but due to the flexibility of linq you loose some of the brevity.On the other hand, writing a full linq query will allow ‘or’ statements which my syntax would not allow for. Let’s see how we could make it closer to what we want. In effect we want to be have a collection that allows you to filter out items based on the available methods that exist in the item type.

In our example we have a collection of HTML elements. I want to call a method on the collection to filter it down to just links (items with an ’a’ tag which is an anchor). That’s fairly easy to accomplish.

On the collection of links I want to filter based on the innerText value on each of the elements. My syntax indicates that we should be able to calling the innerText method on the collection of links. The decision here is what to return when that is called. My initial plan involved returning a key value pair of strings and the elements. This was returned in a custom type that had methods for all the string methods like StartsWith and Contains. If we called the Contains method it would go through the keys and if the key contained that text it would return that element in the collection. Said another way, it would return all the elements that return true for the selected method. When I was done I would return a list of the original type and I could start again and loop as many times as I wanted. It worked.

'Here is a simple object to contain a paired test string and an element
'This keeps them together
>Public Class TextAndElementPair
    Public Text As String
    Public Element As IHTMLElement
    Sub New(ByVal _text As String, ByVal _element As IHTMLElement)
        Text = _text
        Element = _element
    End Sub
End Class

'Here is the object that is returned from the call to 'InnerText' that allows you to call Contains on all the elements
Public Class ElementsStringFilter
    Dim _elements As List(Of TextAndElementPair)

    Sub New(ByVal Elements As List(Of TextAndElementPair))
        _elements = Elements
    End Sub

    Public Function Contains(ByVal Text As String) As List(Of IHTMLElement)
        Dim Elements As New List(Of IHTMLElement)
        For Each Pair In _elements
            If Pair.Text.Contains(Text) Then Elements.Add(Pair.Element)
        Next
        Return Elements
    End Function
End Class

I looked at the code and it looked convoluted and clunky. I also realized that I was creating a copy of most of the objects and more objects with every dot in my syntax. There had to be another way. In my next post I’ll go over what I did next.

Enumerable of String version 3 – Generics to simplify

I continue exploring readability and the framework by investigating the possibility of something similar to an enumerable but with strings. It really is quite different than an enumerable in several ways. I had two previous posts V1 and V2 . I’m going to repeat some information in this post. You can see I’m beginning to call this a Completion List Pattern.

Story

I was on a project where I am reading information from a mainframe travel agency system. I communicate back and forth using strings that represent screens that the travel agent used to see before the internet. These are similar to the 3270 displays but most are smaller. An example would be the inventory screen. The travel agent would type in a hotel and some dates and they would receive a screen indicating what days were available, closed or on request. On a month availability screen there are a lot of letters. under each day for a hotel there is one of three letters. If you have to call the hotel to request a date the letter R was there to indicate that it was on request. If the hotel was closed to arrivals there there was a letter C on that day. If the hotels availability was open and you could come and say then an O was under that day. These letters are called inventory codes.

For working with this data I wanted to put it in proper objects. Link makes it trivial to write queries to find what you want once you have it is objects. I really like enums (enums) because you get the intellisense but the only integer types were allowed for the values. I then had to have a separate object that mapped the integers to the strings found on the screen. That visually separated the string from the enums which complicated upkeep. I’ve been experimenting and here is what I have come up with. It’s not ideal but I learned a lot putting it together.

Goals:

  • Easily map string values to types for parsing
  • Provide intellisense with a statement completion list of values for easy coding
  • Minimize the amount of code needed to implement the pattern

Let’s begin by creating a type to store our inventory codes.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InventoryCode
    Inherits completionListItem
    Public Sub New(ByVal SetText As String)
        MyBase.New(SetText)
    End Sub
    Public Sub New()
        MyBase.New()
    End Sub
End Class

This is actually far more complex than I wanted but apparently you can’t inherit constructors (See my previous post about my question on stackoverflow.com). Any ideas on how to shrink this would be appreciated.

Next we need to list out all the codes in a completion list.

Public NotInheritable Class InventoryCodes
    Inherits completionList
    Public Shared ReadOnly Open As New InventoryCode("O")
    Public Shared ReadOnly Closed As New InventoryCode("C")
    Public Shared ReadOnly OnRequest As New InventoryCode("R")
End Class

That has a lot of words in it but it’s easy enough to follow. Let’s see how the intellisense works

image

Great. Now we can get to business. Let’s assume that I have a variable with data from the screen called ScreenText. I can check to see if it’s available by the following:

If ScreenText = InventoryCodes.Open.Text Then
    Console.WriteLine("Yay! We can stay at the hotel!")
End If

That’s Easy. Now something more difficult. Let’s say I want to convert a screen text directly into the proper Inventorycode type. You could use reflection to iterate through the items to find the right one. The problem with reflection is the speed loss. To mitigate that I created a generic class that created a dictionary once then you can use it several times. I also included a command to find the right item sing that is code you will need to do a lot. First you create a new completionListDictionairy object like below to generate the dictionary and give you the tools. Below I put the proper InventoryCode object in the variable “I”.

Dim InventoryDictionairy As New completionListDictionairy(Of InventoryCode, InventoryCodes)
Dim ScreenText As String = "O"
Dim I As InventoryCode
I = InventoryDictionairy.GetValueFromString(ScreenText)

You can now even loop through all the codes and print them out if you like:

Console.WriteLine(InventoryDictionairy.items.Count)
For Each item In InventoryDictionairy.items
    Console.WriteLine(item.Key.ToString & " : " & item.Value.Text)
Next

Let’s see how this meets our goals

  • Easily map string values to types for parsing : Seems pretty easy after some setup
  • Provide intellisense with a statement completion list of values for easy coding: Intellisense is there
  • Minimize the amount of code needed to implement the pattern: Umm… lots more code than I like so I didn’t really succeed here.

Let me know what you think in the comments but please be kind. I know that this is not production code and probably does not really justify it’s work. It’s an experiment.

Namespace CompletionListHelperNamespace
    Public Class completionListDictionairy(Of t As {completionListItem, New}, ts As {completionList, New})
        Public items As New Dictionary(Of String, t)

        'Get the code from the list created in the new
        Public Function GetValueFromString(ByVal Text As String) As t
            For Each code In items
                If code.Value.Text = Text Then Return code.Value
            Next
            Return Nothing
        End Function

        'Use reflection to put the codes in a list for later fast retrieval
        Sub New()
            Dim TempeStrClass As New ts
            Dim TempeStr As New t
            Dim TypeStrClass As Type = TempeStrClass.GetType
            Dim TypeStr As Type = TempeStr.GetType
            Dim f() As FieldInfo = TypeStrClass.GetFields
            For Each Field In f
                If Field.GetValue(Field).GetType Is TempeStr.GetType Then
                    items.Add(Field.Name, Field.GetValue(Field))
                End If
            Next
        End Sub
    End Class

    Public Class completionListItem
        Public ReadOnly Text As String
        Public Sub New(ByVal SetText As String)
            Text = SetText
        End Sub
        Public Sub New()
        End Sub
    End Class

    Public Class completionList
    End Class
End Namespace

My First Question on stackoverflow.com

I was working on yet another option for the enumerable of string that I have been posting on. I asked “Can you inherit a sub new with parameters in VB?” In 10 minutes I received 4 views. In the first hour I had 6 views. No answers yet.  I’m a little scared that the questions will seem dumb. I searched everywhere I could think of to find the answer. It’s hard when many of the words are so generic. We’ll see where it goes.

I know, Enumerating strings is not really worth this effort. Actually they are not enumerated as they are not counted but I don’t have a better term. While doing this I am learning a lot of the details of the language which I feel is helping me get better at coding.

Enumerable of String ver 2 (VB , enum , .net)

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

In an earlier post about making an enumerable of strings I proposed a method to have string enumerated for better intellisense. I suggest you read that post for the background. I have discovered another way to do something similar. This code also provides the great intellisence of an enumerable but does not use and enumerable. It only works in VB. The big change is a post I found on Stack overflow about the Hidden Features of VB.Net. It is the completionlist tag. Note this tag below. Here is good example is a post by Dustin Campbell – Lesser-Known VB: Customizing the Completion List showing how it is done. In my implementation I also needed a way to find out is a string was in the enumerated items. For that I had to do reflection (WARNING speed reduction). Unlike the previous example this uses full on reflection. I still am not sure if tags are as detrimental as regular reflection. Be sure to do performance testing on this example before using it.

Here is the Completion list XML decorating a new class that will hold the strings.

''' <completionlist cref="InventoryStatusCodes"/>
Public Class InevntoryStatusCode
    Private ReadOnly _Text As String
    Public Sub New(ByVal Text As String)
        _Text = Text
    End Sub
    Public ReadOnly Property GetScreenText() As String
        Get
            Return _Text
        End Get
    End Property
End Class

Here is how we apply the string to the names that will display like when you use an enumerable

Public NotInheritable Class InventoryStatusCodes
    Public Shared ReadOnly Open As New InevntoryStatusCode("O")
    Public Shared ReadOnly Closed As New InevntoryStatusCode("C")
    Public Shared ReadOnly OnRequest As New InevntoryStatusCode("R")
End Class

Here is the function I use when I have some screen text and I want to return the proper enumerated value. If it is supplied a “O” it would return and Open Inventory Status code object.

Public Function ScreenTextToStatusInventoryCode(ByVal ScreenText As String) As InevntoryStatusCode
        Dim i As New InventoryStatusCodes
        Dim t As Type = i.GetType
        Dim f() As FieldInfo = t.GetFields

        Dim isc As InevntoryStatusCode '= InventoryStatusCodes.Open

        For Each Field In f
            isc = Field.GetValue(Field)
            If ScreenText = isc.GetScreenText Then Return isc
        Next

        Return Nothing
    End Function

Here is an example of it being used

'We read in an O string text from the old mainfram screen.
Dim IncomingStringText As String = "O"
If IncomingStringText = InventoryStatusCodes.OnRequest.GetScreenText Then
    'This if statement can be used to test if it was Open 
End If

'We can also store it in an object like
Dim Codes As New List(Of InevntoryStatusCode)

Codes.Add(ScreenTextToStatusInventoryCode(IncomingStringText))

Here is a screen shot of the intellisense in action

image

Let me know what you think but please be kind.

Enum Intellisense

Enumerable of string (VB, enum, .net)

The Story

I was recently working on an interface to an old mainframe. I was screen scraping a terminal emulator and putting the data into objects for analysis. It was actually fun as I was using some technologies I hadn’t used yet. I wanted to use enums for my object so the intellisense would look real good. The problem is that each item translates to a character or short string on the screen. I wanted a way to keep track of the screen text that represented the enum. For an example lets use an old travel agency system for hotels. There is a screen that displays availability of a hotel. There is a screen that will display the availability of a hotel for a specific day. Each day will be either open, closed, or request. On the text screen from the mainframe these were represented as O=open, C=closed, and R=request. I created a quick enum and then I had to figure out how to associate the text from the screen to the enum in a format that is easy to read in case we need to make a change in the future (even though all these systems are going away.) Here was my first attempt

Public Enum InventoryStatusCode
    Open
    Closed
    OnRequest
End Enum

That was easy and clear enough. Sow to associate the text on the terminal screen to the proper enum

Function GetInventoryStatusCode(ByVal ScreenText As String) As InventoryStatusCode
    Select Case ScreenText
        Case "O"
            Return InventoryStatusCode.Open
        Case "C"
            Return InventoryStatusCode.Closed
        Case "R"
            Return InventoryStatusCode.OnRequest
        Case Else
            Throw New ArgumentException("Screen text " & ScreenText & " not valid for Inventory Status Code")
    End Select
End Function

Wow, is that a lot of code for so little. I am spoiled when I am using enums that can equate to meaningful numbers. If the system used 1=open, 2=closed, and 3=request then I could use the number but I couldn’t request a change to a system that is older than I am. I could use constants but I like how the enums were strongly types and grouped together so they just pop up after you hit the equal sign. Enum allows you to assign a type but it must be I searched for quite a while and found several posts about how to match a string to the enum name but I also discovered that the framework has that built in now with [Enum].Parse(GetType(InventoryStatusCode), “O”). The problem with this approach is that the enums would be InventoryStatusCode.O instead of InventoryStatusCode.Open. That tends to deflect the benefit of the readability of enums. Also, for this specific implementation some of the screen codes were special characters and blanks which would not be allowed. I finally ran across a post suggesting attributes and I like how concise it looked. There was a built in description attribute but I didn’t use that here because I might want descriptions also in the future. It also provided me the opportunity to try my hand at writing my own attribute. Hopefully it’s won’t cause confusion with the added code in this example.

My Solution

Here is what I came up with. There are probably other ways. Let me know what you would do in the comments. This example supposes that you have three enum items of Open, Closed and OnRequest and you with to associate the text O,C and R with them respectively.

Public Enum InventoryStatusCode
    <ScreenText("O")> Open
    <ScreenText("C")> Closed
    <ScreenText("R")> OnRequest
End Enum

Then I can use the helper function below. If I pass in “O” I will receive the InventoryStatusCode.Closed like below:

ParseScreenText(GetType(InventoryStatusCode), "O")

I can also accomplish the opposite and receive the “O” by doing the following:

InventoryStatusCode.Open.GetScreenText

That is how it looks when used. Looks pretty clear to me. We will need some more code make it all work

Here is the attribute definition:

''' <summary>
''' USed to identify the text on the terminal screen represented by an enum
''' </summary>
''' <remarks></remarks>
<AttributeUsage(AttributeTargets.All)> _
Public Class ScreenText
    Inherits System.Attribute

‘Private fields. Private _Text As String

‘This constructor defines two required parameters: name and level. Public Sub New(ByVal Text As String) Me._Text = Text End Sub

‘Define Name property. ‘This is a read-only attribute. Public Overridable ReadOnly Property Text() As String Get Return _Text End Get End Property End Class

Here is the function so you can pass in some screen text and receive the associated enum. I couldn’t get this to work as an extension of enum which would have been nice.

''' <summary>
    ''' Returns the proper enumerator that matches the provided screen text
    ''' </summary>
    ''' <param name="en">Enumerator type to search</param>
    ''' <param name="ScreenText">Screen text to be matched to an enumerator</param>
    ''' <returns>Proper enumerator that matched the screen text</returns>
    ''' <remarks></remarks>
    <Extension()> _
    Public Function ParseScreenText(ByVal en As Type, ByVal ScreenText As String) As [Enum]
        'Dim enumitem As [Enum]
        For Each enumitem In [Enum].GetValues(en)
            If GetScreenText(enumitem) = ScreenText Then
                Return enumitem
            End If
        Next
        Return Nothing
    End Function
End Module

Here is the extension on the enum class. Module enumExtensions ”’ <summary> ”’ Provides the attribute value ScreenText on the enumerator. ”’ The screen text is the representation of the value on a terminal screen ”’ </summary> ”’ <param name=”en”>Enumerator for which the screen text will be returned</param> ”’ <returns>String of the text representation on a terminal screen for this enumerator</returns> ”’ <remarks></remarks> <Extension()> _ Public Function GetScreenText(ByVal en As [Enum]) As String Dim type As Type = en.[GetType]() Dim memInfo As MemberInfo() = type.GetMember(en.ToString()) If memInfo IsNot Nothing AndAlso memInfo.Length > 0 Then Dim attrs As Object() = memInfo(0).GetCustomAttributes(GetType(ScreenText), False) If attrs IsNot Nothing AndAlso attrs.Length > 0 Then Return DirectCast(attrs(0), ScreenText).Text End If End If Return en.ToString() End Function End Module

Isn’t that slower?

The main disadvantage of this is that it appears to use reflection which reduces performance. It seems to me that Dynamic data uses attributes and thus reflection a lot. They may have a way to perform it once up front which reduces the impact. In my application I had seconds of wait times between commands due to legacy systems so the performance should not be a factor.

Isn’t that bad Object Oriented Design?

It’s considered bad object oriented design because “we’re asking another class to retrieve information about our enum type”. Isn’t the enum.parse doing about the same thing though? Would it be good OO if I could get the extension method to work? I’m thinking it’s worth it for this case.

Why not just make a class?

I found a post suggesting that you strongly type your domain values which accomplishes much of the same goals and is probably more performant when looking up the codes. I like the syntactic goodness of enums when coding. You don’t get this great intellisense from a class. when you hit the equals key it just lists the applicable items. When using a class it lists all the objects.

Enum Intellisense

It makes it quick for coding. If someone knows how to get intellisense to automatically show you the options after hitting the equal sign then I would suggest a class. The syntax of the class is a little more verbose but is as legible in my opinion. I guess you could just remember that the type begins with “inven” and the the intellisense would pick up the rest.

Summary Justification

In this case I feel the less verbose and clear syntax makes up for the performance and an additional helper class. I could go the the class option if performance became an issue. Tell me what you think.

Other Sources

I’ve done more searching while writing this post and found a whole lot more.

Who thought this area was so intricate. I guess that is because enums are really syntactic sugar in a way. I think this needs more investigations. Please comment your ideas and suggestions.