Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function returning an object with type specified in the argument

Tags:

vb.net

How can I create a function that returns an object of a certain type, which the user of the function specify in the argument (using vb.net 2010) ?

Private Function TryThis(ByVal t As Type) As Object
    Dim n = New t
    Return n
End Function

The code above doesn't work, but maybe it can explain what I want to achieve.

Using this feature, I want to hydrate my data transfer objects from datatable. Client will just call this function, specifying which DTO the client wants, and this function will just create that DTO and populating the properties with reflection GetType.GetProperties().

like image 825
Endy Tjahjono Avatar asked Mar 22 '11 05:03

Endy Tjahjono


People also ask

Can functions return any type of object?

A function may be defined to return any type of value, except an array type or a function type; these exclusions must be handled by returning a pointer to the array or function. When a function does not return a value, void is the type specifier in the function declaration and definition.

Which function return data type of an object?

The type() function is mostly used for debugging purposes. Two different types of arguments can be passed to type() function, single and three arguments. If a single argument type(obj) is passed, it returns the type of the given object.

Can a function return an object?

A function can also return objects either by value or by reference. When an object is returned by value from a function, a temporary object is created within the function, which holds the return value. This value is further assigned to another object in the calling function.

Can an object be a return type?

User-defined functions and class methods can define return types as object references (as class or interface types). When an object is passed locally, class instances are always returned by reference. Thus, only a reference to an object is returned, not the object itself.


1 Answers

Here's a very basic example that uses generics. The method GetPropFromDatabase just uses a Select Case but instead of that you'd obviously put your real database lookup call.

Option Explicit On
Option Strict On

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim X = CreateObject(Of TestClass)()

        Trace.WriteLine(X.PropertyA)
        Trace.WriteLine(X.PropertyB)

        Me.Close()
    End Sub

    ''//Of T as New means that the object must have a constructor
    Private Function CreateObject(Of T As New)() As T
        ''//Create our object
        Dim O As New T
        ''//Get the type properties
        Dim Props = GetType(T).GetProperties()
        ''//Loop through each property
        For Each P In Props
            ''//Set the value of our return type by property name
            P.SetValue(O, GetPropFromDatabase(P.Name), Nothing)
        Next
        ''//Return our object
        Return O
    End Function
    ''//This function would obviously do a lot more
    Private Shared Function GetPropFromDatabase(ByVal name As String) As String
        Select Case name
            Case "PropertyA"
                Return "Value1"
            Case "PropertyB"
                Return "Value2"
        End Select

        Throw New ApplicationException(String.Format("Unknown database column : {0}", name))
    End Function
End Class
Public Class TestClass
    Public Property PropertyA As String
    Public Property PropertyB As String
End Class

EDIT

You might have to play with BindingFlags on GetProperties() depending on how your object is setup.

EDIT 2

You might also want to look into using Custom Attributes. For instance, if you've got a column in your database called [First Name] that obviously can't exist as an object property because of the space. With a custom attribute you can flag certain properties to be ignored or parsed in a special manner. The code below shows an extended version of the above code.

Option Explicit On
Option Strict On

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim X = CreateObject(Of TestClass)()

        Trace.WriteLine(X.PropertyA)
        Trace.WriteLine(X.PropertyB)
        Trace.WriteLine(X.FirstName)

        Me.Close()
    End Sub

    ''//Of T as New means that the object must have a constructor
    Private Function CreateObject(Of T As New)() As T
        ''//Create our object
        Dim O As New T
        ''//Get the type properties
        Dim Props = GetType(T).GetProperties()

        ''//Will hold the name of the database column to get the value of
        Dim PropName As String
        ''//Will hold our collection of attributes on the property
        Dim CustomAttributes() As Object
        ''//Loop through each property
        For Each P In Props
            ''//Default the value to the property name
            PropName = P.Name
            ''//Try to get any custom attributes for the property
            CustomAttributes = P.GetCustomAttributes(True)
            ''//See if we have anything to work with
            If (CustomAttributes IsNot Nothing) AndAlso (CustomAttributes.Count > 0) Then
                ''//Loop through each attribute
                For Each A In CustomAttributes
                    ''//If the attribute is our custom one defined below
                    If TypeOf A Is ColumnNameInDatabase Then
                        ''//Use the manually set column name instead
                        PropName = DirectCast(A, ColumnNameInDatabase).ColumnNameInDatabase
                        ''//No reason to loop through any more attributes so exit
                        Exit For
                    End If
                Next
            End If
            ''//Set the value of our return type by property name
            P.SetValue(O, GetPropFromDatabase(PropName), Nothing)
        Next
        ''//Return our object
        Return O
    End Function
    ''//This function would obviously do a lot more
    Private Shared Function GetPropFromDatabase(ByVal name As String) As String
        Select Case name
            Case "PropertyA"
                Return "Value1"
            Case "PropertyB"
                Return "Value2"
            Case "First Name"
                Return "Bob Dole"
        End Select

        Throw New ApplicationException(String.Format("Unknown database column : {0}", name))
    End Function
End Class
Public Class TestClass
    Public Property PropertyA As String
    Public Property PropertyB As String
    <ColumnNameInDatabase("First Name")> Public Property FirstName As String
End Class
Public Class ColumnNameInDatabase
    Inherits Attribute
    Private _ColumnNameInDatabase As String
    Public ReadOnly Property ColumnNameInDatabase As String
        Get
            Return Me._ColumnNameInDatabase
        End Get
    End Property
    Public Sub New(ByVal columnNameInDatabase As String)
        Me._ColumnNameInDatabase = columnNameInDatabase
    End Sub
End Class
like image 153
Chris Haas Avatar answered Oct 24 '22 23:10

Chris Haas