2011-03-22 25 views
5

vb.net 2010を使用して、関数のユーザーが引数で指定する特定の型のオブジェクトを返す関数を作成するにはどうすればよいですか?引数で指定された型のオブジェクトを返す関数

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

上記のコードは機能しませんが、達成したいことを説明することができます。

この機能を使用して、データ転送オブジェクトをデータテーブルから水和したいと考えています。クライアントはこの関数を呼び出すだけで、クライアントが望むDTOを指定します。この関数はそのDTOを作成し、そのプロパティを反映GetType.GetProperties()に設定します。

答えて

4

ここには、ジェネリックを使用する非常に基本的な例があります。方法GetPropFromDatabaseSelect Caseを使用していますが、実際のデータベース検索呼び出しを行うことは明らかです。あなたのオブジェクトのセットアップ方法に応じてGetProperties()BindingFlagsでプレイする必要がある場合があります

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

EDIT 2

ます。また、カスタム属性を使用してに見たいと思うかもしれません。例えば、データベースに[First Name]という名前の列がある場合は、スペースのためにオブジェクトのプロパティとして存在できないことは明らかです。カスタム属性を使用すると、特定のプロパティを無視したり、特別な方法で解析したりすることができます。下のコードは、上記のコードの拡張バージョンを示しています。

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 
1

キーワードのChris Haasに感謝して、私はさらにトピックを研究することができました。私はanother answerOf T As Newを使用していないことを発見しました。これは私のDTOがコンストラクタを宣言していないために最終的に使用します。レコードの

は、ここで私は最終的に使うものです:

Private Function DataRowToObject(Of T)(ByVal source As DataRow) As T 
    Dim destination = GetType(T).GetConstructor(System.Type.EmptyTypes).Invoke({}) 
    Dim props = destination.GetType.GetProperties() 
    Dim propnames = props.Select(Function(x) x.Name.ToLower) 

    For Each col In source.Table.Columns 
     Dim colname = col.ColumnName.ToLower() 
     If propnames.Contains(colname) Then 
      Dim prop = props.Where(Function(x) x.Name.ToLower = colname).First 
      If IsDBNull(source(col)) And prop.PropertyType Is GetType(String) Then 
       prop.SetValue(destination, "", Nothing) 
      ElseIf IsDBNull(source(col)) Then 
       prop.SetValue(destination, Nothing, Nothing) 
      Else 
       prop.SetValue(destination, source(col), Nothing) 
      End If 
     End If 
    Next 

    Return destination 
End Function 

Protected Function DataTableToList(Of T)(ByVal source As DataTable) As IList(Of T) 
    Dim destination As New List(Of T) 

    For Each row In source.Rows 
     Dim obj = DataRowToObject(Of T)(row) 
     destination.Add(obj) 
    Next 

    Return destination 
End Function 

は、ここで上記の関数を使用するクライアントです:

Public Function PeopleAll() As IList(Of DTO.People) 
    Dim ResultTbl As New DataTable 
    adp.TableLoad("select * from people", ResultTbl) 

    Dim result = DataTableToList(Of DTO.People)(ResultTbl) 
    Return result 
End Function 

は、ここに私のデータ転送オブジェクトのサンプルです:

Public Class People 
    Public Overridable Property ID As Int64 
    Public Overridable Property Name As String 
    Public Overridable Property Email As String 
End Class 
関連する問題