Wednesday, November 19, 2008

Typed Functions with Parameterized Constructors

Recently I encountered this scenario where a method began to become a perfect candidate to be parameterized as I was using it for more and more newly created objects.

Private Shared Function AssembleData( _
ByVal dataList As List(Of PermissionInfoData) _
) As List(Of PermissionInfo)

Dim permissions As New List(Of PermissionInfo)

For Each data As PermissionInfoData In dataList
permissions.Add(New PermissionInfo(data))
Next

Return permissions
End Function

It is basically an Assembler method that takes a list of a "data" class and converts it into a list of "Info" Class.
As I was building more and more such Info-Data pairs of objects where required and I had to create more and more overloads for the AssembleData function.

So I quickly started writing a Typed function only to get stuck real bad in the next few seconds:

Private Shared Function AssembleData(Of TInfo As {Class, New}, TData)( _
ByVal dataList As List(Of TData) _
) As List(Of TInfo)

'Return permissions
Dim infoList As New List(Of TInfo)
Dim info As New TInfo(TData)

For Each data As TData In dataList
infoList.Add(info)
Next

Return infoList
End Function


The problem was the Info class Constructor takes the data as a parameter and would instantiate itself based on that.
I tried implementing an interface but was going in all directions without focus.

I then took help from one of the google groups and here is the solution.
.Net does not support parameterized constructors but there is this workaround which worked like charm:

Private Shared Function AssembleData(Of TInfo, TData, TAssemblerFactory As {Class, IAssemblerFactory(Of TInfo, TData), New})( _
ByVal dataList As List(Of TData) _
) As List(Of TInfo)

Dim infoList As New List(Of TInfo)
Dim info As TInfo
Dim factory As TAssemblerFactory

For Each data As TData In dataList
factory = New TAssemblerFactory
info = factory.CreateNew(data)
infoList.Add(info)
Next

Return infoList
End Function

Interface IAssemblerFactory(Of TInfo, TData)
Function CreateNew(ByVal data As TData) As TInfo
End Interface


Public Class UserInfoAssemblerFactory
Implements IAssemblerFactory(Of UserInfo, UserInfoData)


Public Function CreateNew( _
ByVal data As UserInfoData _
) As UserInfo Implements IAssemblerFactory(Of UserInfo, UserInfoData).CreateNew

Return New UserInfo(data)
End Function

End Class

No comments: