Skip to content

Commit

Permalink
Specifying the ItemInstanceAttribute and overriding ItemInstance_ for…
Browse files Browse the repository at this point in the history
… DatabaseObjects.Generic.DatabaseObjects* types is optional. Closes #40.

ItemInstanceAttribute does not need to be specified if a DatabaseObjects.Generic.DatabaseObjects collection is utilised because the T argument is instead used. Furthermore, overriding ItemInstance_ for non-DatabaseObjects.Generic.DatabaseObjects*UsingAttributes classes is no longer necessary because the T argument is used to determine the ItemInstance type to create.
  • Loading branch information
hisystems committed Mar 28, 2012
1 parent 8cc2ffe commit 3027a5a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 22 deletions.
66 changes: 66 additions & 0 deletions Database/DatabaseObjectsItemInstance.vb
@@ -0,0 +1,66 @@

' ___________________________________________________
'
' © Hi-Integrity Systems 2012. All rights reserved.
' www.hisystems.com.au - Toby Wicks
' ___________________________________________________
'

Option Strict On
Option Explicit On

Imports System.Reflection

Friend Module DatabaseObjectsItemInstance

''' <summary>
''' </summary>
''' <param name="itemInstanceTypeToCreate">The type of DatabaseObjects.DatabaseObject to create.</param>
''' <param name="databaseObjects">Parameter that is passed to the constructor of the DatabaseObject to create. If there is a default constructor then this argument is not used.</param>
Public Function CreateItemInstance(itemInstanceTypeToCreate As Type, databaseObjects As Global.DatabaseObjects.DatabaseObjects) As IDatabaseObject

Dim objObjectInstance As Object = Nothing

For Each objConstructor As ConstructorInfo In itemInstanceTypeToCreate.GetConstructors(BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
Dim objConstructorParameters As ParameterInfo() = objConstructor.GetParameters()
If objConstructorParameters.Length = 0 Then
objObjectInstance = objConstructor.Invoke(Nothing)
Exit For
ElseIf objConstructorParameters.Length = 1 AndAlso (objConstructorParameters(0).ParameterType.IsSubclassOf(GetType(DatabaseObjects)) OrElse objConstructorParameters(0).ParameterType.Equals(GetType(DatabaseObjects))) Then
objObjectInstance = objConstructor.Invoke({databaseObjects})
Exit For
End If
Next

If objObjectInstance Is Nothing Then
Throw New Exceptions.DatabaseObjectsException("An empty constructor or constructor with argument DatabaseObjects.DatabaseObjects (or subclass) could not be found for type '" & itemInstanceTypeToCreate.FullName & "'. This type has been specified by the ItemInstanceAttribute for the type '" & databaseObjects.GetType.FullName & "' or as the T argument.")
ElseIf Not TypeOf objObjectInstance Is IDatabaseObject Then
Throw New Exceptions.DatabaseObjectsException("'" & itemInstanceTypeToCreate.FullName & "' does not implement IDatabaseObject or inherit from DatabaseObject. Type was specified for use by the ItemInstanceAttribute on the type '" & databaseObjects.GetType.FullName & "'")
Else
Return DirectCast(objObjectInstance, IDatabaseObject)
End If

End Function

''' <summary>
''' Returns the first generic argument that is passed to the DatabaseObjects.Generic.DatabaseObjects class (or super class).
''' This is used to determine the type of item that the collection represents and the type of class that should be returned from
''' the IDatabaseObjects.ItemInstance function.
''' </summary>
Public Function GetGenericCollectionTArgument(collectionType As Type) As Type

Dim currentCollectionType As Type = collectionType

While currentCollectionType IsNot Nothing AndAlso Not (currentCollectionType.IsGenericType AndAlso currentCollectionType.GetGenericArguments(0).IsSubclassOf(GetType(DatabaseObject)))
currentCollectionType = currentCollectionType.BaseType
End While

If currentCollectionType IsNot Nothing Then
Return currentCollectionType.GetGenericArguments(0)
Else
Throw New Exceptions.DatabaseObjectsException("The ItemInstance type could not be found for '" & collectionType.FullName & "' because it does not inherit from DatabaseObjects.Generic.DatabaseObjects")
End If

End Function

End Module
31 changes: 10 additions & 21 deletions Database/DatabaseObjectsUsingAttributesHelper.vb
Expand Up @@ -73,31 +73,20 @@ Friend Class DatabaseObjectsUsingAttributesHelper

Public Function ItemInstance() As IDatabaseObject

If pobjItemInstance Is Nothing Then
Throw New Exceptions.DatabaseObjectsException("ItemInstanceAttribute has not been specified or the ItemInstance function was not overridden for type '" & pobjDatabaseObjects.GetType.FullName & "'")
End If
Dim itemInstanceType As Type

Dim objObjectInstance As Object = Nothing

For Each objConstructor As ConstructorInfo In pobjItemInstance.Type.GetConstructors(BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic)
Dim objConstructorParameters As ParameterInfo() = objConstructor.GetParameters()
If objConstructorParameters.Length = 0 Then
objObjectInstance = objConstructor.Invoke(Nothing)
Exit For
ElseIf objConstructorParameters.Length = 1 AndAlso (objConstructorParameters(0).ParameterType.IsSubclassOf(GetType(DatabaseObjects)) OrElse objConstructorParameters(0).ParameterType.Equals(GetType(DatabaseObjects))) Then
objObjectInstance = objConstructor.Invoke({pobjDatabaseObjects})
Exit For
End If
Next

If objObjectInstance Is Nothing Then
Throw New Exceptions.DatabaseObjectsException("An empty constructor or constructor with argument DatabaseObjects.DatabaseObjects (or subclass) could not be found for type '" & pobjItemInstance.Type.FullName & "'. This type has been specified by the ItemInstanceAttribute for the type '" & pobjDatabaseObjects.GetType.FullName & "'")
ElseIf Not TypeOf objObjectInstance Is IDatabaseObject Then
Throw New Exceptions.DatabaseObjectsException("'" & pobjItemInstance.Type.FullName & "' does not implement IDatabaseObject or inherit from DatabaseObject. Type was specified for use by the ItemInstanceAttribute on the type '" & pobjDatabaseObjects.GetType.FullName & "'")
If pobjItemInstance Is Nothing Then
Try
itemInstanceType = DatabaseObjectsItemInstance.GetGenericCollectionTArgument(pobjDatabaseObjects.GetType)
Catch ex As Exceptions.DatabaseObjectsException
Throw New Exceptions.DatabaseObjectsException("ItemInstanceAttribute has not been specified and " + ex.Message)
End Try
Else
Return DirectCast(objObjectInstance, IDatabaseObject)
itemInstanceType = pobjItemInstance.Type
End If

Return DatabaseObjectsItemInstance.CreateItemInstance(itemInstanceType, pobjDatabaseObjects)

End Function

Public ReadOnly Property DistinctFieldName() As String
Expand Down
1 change: 1 addition & 0 deletions DatabaseObjects.vbproj
Expand Up @@ -122,6 +122,7 @@
<Compile Include="Contraints\NumberIsMaximumOrLesserConstraint.vb" />
<Compile Include="Contraints\StringMaxLengthConstraint.vb" />
<Compile Include="Database\ConnectionScope.vb" />
<Compile Include="Database\DatabaseObjectsItemInstance.vb" />
<Compile Include="Database\RootContainer.vb" />
<Compile Include="Database\DatabaseObjectsUsingAttributes.vb" />
<Compile Include="Database\DatabaseObjectsUsingAttributesHelper.vb" />
Expand Down
11 changes: 10 additions & 1 deletion Generic/DatabaseObjects.vb
Expand Up @@ -497,6 +497,9 @@ Namespace Generic
''' It is suffixed with an underscore so that it does not conflict with the underlying
''' non-generic equivalent ItemInstance function. It's purpose is indentical to the
''' non-generic version.
''' If this function is not overriden an object of type T will be created.
''' The type T must have a default constructor or a constructor that accepts a type of
''' DatabaseObjects.Generic.DatabaseObjects or a subclass.
''' </summary>
'''
''' <example>
Expand All @@ -510,7 +513,13 @@ Namespace Generic
''' </example>
''' --------------------------------------------------------------------------------
'''
Protected MustOverride Function ItemInstance_() As T
Protected Overridable Function ItemInstance_() As T

Dim itemInstanceType As Type = DatabaseObjectsItemInstance.GetGenericCollectionTArgument(Me.GetType)

Return DirectCast(DatabaseObjectsItemInstance.CreateItemInstance(itemInstanceType, Me), T)

End Function

''' --------------------------------------------------------------------------------
''' <summary>
Expand Down

0 comments on commit 3027a5a

Please sign in to comment.