2014-06-13 176 views
1

我試圖能夠將一個Type參數傳遞給名爲ConvertList的函數,並讓該函數創建指定類型的某些實例。所以,如果我傳入Foo類型,函數將創建Foo類型的新對象,並將創建的對象放入自定義List對象(SLMR_OBjList)中。將參數傳遞給泛型類型VB.Net中的新構造函數泛型

功能是定義一個通用類:

Public Class BOIS_Collection_Base(Of T) 

功能將接受比什麼是類定義了其他類型。所以,如果我們創建一個BOIS_Collection_Base(Of MyTypeA)的實例,我們可以調用函數ConvertList(Of MyTypeB)

我想私有變量_convertedList是一個不同於類的類型。這可能嗎?我似乎只能用(T)來定義它。

這是我到目前爲止有:

Public Class BOIS_Collection_Base(Of T) 
    Private _convertedList As SLMR_ObjList(Of T) ' I can only seem to define this as (Of T), but want to make sure I can pass in a Type other than the Base(Of T) 
    Public Function ConvertedObjList(Of myT)() As SLMR_ObjList(Of T) ' Should this be (Of T) or (Of myT) since I want it to use whatever Type is passed in 
     For Each tempVar In Me.ObjList 
      Dim newitem As myT = Activator.CreateInstance(GetType(myT), tempVar) 
      ' Next line won't compile, says on newitem 'Value of type 'myT' cannot be converted to 'T' 
      _convertedList.Add(newitem) 
     Next 
     _convertedList.Sort_Direction = Me.Sort_Direction 
     _convertedList.Sort_Expression_List = Me.Sort_Expression_List 
     Return _convertedList 
    End Function 

這裏是我想能夠做到:

Dim mainCollInstance As New BOIS_Collection_Base(Of MyTypeA) 
.... 
'Code that populates the BOIS_Collection_Base.ObjList property with an SLMR_ObjList(Of MyTypeA) 
.... 
' Now I want to take that ObjList, and cast all the items in it to MyTypeB 
Dim newListObj As SLMR_ObjList(Of MyTypeB) = mainCollInstance.ConvertList(Of MyTypeB) 

這可能嗎?我錯了嗎?

針對Plutonix:
如果我定義_convertedList的方法中,像這樣:

Public Function ConvertedObjList(Of myT)() As SLMR_ObjList(Of myT) 
    Dim _convertedList = New SLMR_ObjList(Of myT) 

我的錯誤去了,和方法我想要做什麼,但_convertedList不再是持續性的目的。

+0

我不確定這是泛型的問題,但你如何實現繼承。如果'MyTypeA'和'MyTypeB'相關,那麼集合類可能應該是'(Of AB_BaseClass)'。更重要的是,如果他們是相關的,那麼它應該很容易從另一個自己創建一個實例:'newItem = New myTypeA(myTypeB)' – Plutonix

+0

我不知道我明白了。請查看更新。 –

+2

如果你想保存它,這意味着你總是將相同的類型傳遞給'ConvertedObjList(Of T)'函數,對吧? –

回答

1

如果您想保留列表,那麼您無法真正讓消費代碼每次都爲列表傳遞不同的類型。這並沒有多大意義,除非每次調用它時,只需要該函數返回包含給定類型對象的持久列表部分。如果是這種情況,那麼您只需聲明_convertedList As SLMR_ObjList(Of Object),然後過濾它並根據需要將其轉換爲正確的類型。如果,但是,如果我懷疑是這種情況,消費者總是會要求在每次調用該函數時將其轉換爲相同類型,那麼該輸出類型實際上並不是函數調用的屬性。相反,它是全班的財產。在這種情況下,你應該讓你的類需要兩個泛型類型參數,就像這樣:

Public Class BOIS_Collection_Base(Of T, TOut) 
    Private _convertedList As SLMR_ObjList(Of TOut) 

    Public Function ConvertedObjList() As SLMR_ObjList(Of TOut) 
     For Each tempVar As T In Me.ObjList 
      Dim newitem As TOut = DirectCast(Activator.CreateInstance(GetType(TOut), tempVar), TOut) 
      ' Next line won't compile, says on newitem 'Value of type 'myT' cannot be converted to 'T' 
      _convertedList.Add(newitem) 
     Next 
     _convertedList.Sort_Direction = Me.Sort_Direction 
     _convertedList.Sort_Expression_List = Me.Sort_Expression_List 
     Return _convertedList 
    End Function 
End Class 
0

基於前人的有關問題和假設MyTypeA和MyTypeB從同一類繼承(沒有得到回答)你可能不需要這種泛型。無論如何,這應該有助於問題的部分。我還未看到泛型適合,因爲繼承可以做你想做什麼就:

Class MustInherit BiosItem 
    Public Property Name As String 
    Public Property TypeCode As String 
    ... 
    MustOverride Function Foo(args...) As Type 

    Overridable Property FooBar As String  
    ' etc - the more stuff in the base class the better 

End Class 
Class TypeA 
    Inherits ABClass 

    Public Sub New 
     MyBase.New  ' stuff common to all child types 
     TypeCode = "A" ' EZ type ID rather than GetType 
     ... 
    End Sub 
End Class 

類的TypeB是相同的,但初始化類型碼爲「B」。對於C-Z也是如此。這些允許您輪詢對象而不需要GetType:If thisObj.TypeCode = "A" Then...。現在,集合類:

Public Class BIOSItems 
    Inherits Collection(Of BiosItem) 
    ' inheriting from Collection<T> provides Add, Count, IndexOf for us 
    ' most important the Items collection 
    ' 
End Class 

鍵入集合作爲BiosItem將允許它TypeATypeJTypeQ。原樣,您的收藏將僅保留一個類型。這是有效的,因爲GetType(TypeA)的項目也是GetType(BiosItem)。最後請參閱註釋。

將一個項目轉換爲另一個項目看起來似乎很大程度上將由正在創建或轉換爲的NEW項目處理。因爲他們很可能是非常相似的話,就可以通過一個構造函數重載來處理(如果它們不相似,以及我們非常走上錯誤的道路):

' a ctor overload to create the new thing based on the old things props 
Public Sub New(oldThing As BiosItem) 
    MyClass.New   ' start with basics like TypeCode, MyBase.New 

    With BiosItem   ' coversion 
     myFoo = .Foo 
     myBar = .Bar  ' copy common prop vals to self 
     ... 
     Select Case .TypeCode 
      Case "B" 
       myProp1 = .Prop33  ' conversions 
       myProp3 = .Prop16 + 3.14 
       ... 
     End Select 

     ' then initialize stuff unique to this type maybe 
     ' based on other props 
     If .PropX = "FooBar" Then myPropZ = "Ziggy" 
    End With 
End Sub 

代碼來創建,轉換,存儲:

Dim varOldBItem As TypeB = myBiosCol(ndx) ' get old item 
Dim varAItem As New TypeA(varOldBItem)  ' call the ctor above 
myBiosCol.Add(varAItem)      ' add new item 
myBiosCol.Remove(varoldBItem)    ' delete the old if need be 

如果BOIS_Collection_Base總是應該包含MyTypeA,然後鍵入它的方式(從Collection<T>繼承,以便似乎仍然)。如果MyTypeB對象永遠不會直接添加到集合中,但首先將其轉換爲MyTypeA(Edit會使這一點不那麼清晰),但上述大部分仍然適用,但繼承除外。 MyTypeA上的一個ctor過載仍然可以使用一箇舊的B對象並基於它創建它自己。如果不從同一個基類繼承,我不會傾向於通過ctor來完成,但可以完成。

相關問題