2011-05-24 173 views
5

我繼承了一些代碼,當我看着它時,它讓我感到畏縮。有沒有更優雅的方式來編寫以下內容?有沒有一種優雅的方式來編寫這段代碼?

Dim myItem As DTO.MyBaseClass = Nothing 
Dim myType As String = GetTypeString() 
Select Case myType 
    Case Is = "Case1" 
    myItem = Bus.BusManager(Of DTO.MyClass1).Read() 
    Case Is = "Case2" 
    myItem = Bus.BusManager(Of DTO.MyClass2).Read() 
'... etc etc for 30 lines 

是否有一種方法可以將字符串映射到類類型,然後只是像這樣一行?或者類似的東西?

myItem = Bus.BusManager(Of MappingDealy(myType)).Read() 

回答

1

由於BusManager是通用類型,因此必須在編譯時指定傳入Of <type>的類型。它不像傳統參數,您可以在運行時更改。

從你列出的代碼BusManager實際上做了什麼還不清楚。如果它所做的只是創建一個Generic類型的實例,那麼創建它的人可能不會真正理解泛型。您是否有能力修改BusManager的工作方式,還是僅限於按原樣使用它?

正如@jmoreno提到的,您可以使用反射從包含類型名稱的字符串中創建一個類型的實例。下面是如何將工作:

Imports System.Reflection 
Imports System.IO 

Public Class ObjectFactory 
    Private Shared Function CreateObjectFromAssembly(ByVal assembly As Assembly, ByVal typeName As String) As Object 
     ' resolve the type 
     Dim targetType As Type = assembly.GetType(typeName) 
     If targetType Is Nothing Then 
      Throw New ArgumentException("Can't load type " + typeName) 
     End If 

     ' get the default constructor and instantiate 
     Dim types(-1) As Type 
     Dim info As ConstructorInfo = targetType.GetConstructor(types) 
     Dim targetObject As Object = info.Invoke(Nothing) 
     If targetObject Is Nothing Then 
      Throw New ArgumentException("Can't instantiate type " + typeName) 
     End If 

     Return targetObject 
    End Function 

    Public Shared Function CreateObject(ByVal typeName As String) As Object 
     Return CreateObjectFromAssembly(Assembly.GetExecutingAssembly, typeName) 
    End Function 

    Public Shared Function CreateObject(ByVal typeName As String, ByVal assemblyFileName As String) As Object 
     Dim assemblyFileInfo = New FileInfo(assemblyFileName) 
     If assemblyFileInfo.Exists Then 
      Return CreateObjectFromAssembly(Reflection.Assembly.LoadFrom(assemblyFileName), typeName) 
     Else 
      Throw New ArgumentException(assemblyFileName + " cannot be found.") 
     End If 
    End Function 

End Class 

在生產應用程序,我可能會設置返回類型爲所有的這些方法,我的基類或接口。只要確保你傳遞完整的typeName包括命名空間。

有了這一工廠類,那麼你的代碼的優雅版會是這個樣子:

Dim myItem as DTO.MyBaseClass = ObjectFactory.CreateObject("DTO." & GetTypeString()) 
+0

哇,看起來不錯,謝謝一堆! – 2011-06-02 19:32:17

0

首先,切勿使用Case Is =從不初始化Nothing。因此,一個快速之一將是:

Dim myItem As DTO.MyBaseClass 
Select Case GetTypeString() 
    Case "Case1" 
     myItem = Bus.BusManager(Of DTO.MyClass1).Read() 
    ' etc etc 

但由於您使用的模板,真的沒有辦法,除非你想使用反射,這是在稍微乾淨和更短的代碼爲代價的效率極其低下的映射它。您還可以添加Imports DTO以保存124個字符,還可以通過總線保存另外120個字符。

+1

你能詳細闡述從未使用'的情況是='從不初始化爲'沒什麼'?我對VB比較陌生。 – 2011-05-25 02:51:49

+0

'Case Is = xxx'直接等於'Case xxx',所以沒有意義 - 它只是增加了語法噪音。將引用類型初始化爲'Nothing'也是毫無意義的,因爲這是默認情況下的。有時可以更清楚地將'布爾值'初始化爲'假'和數字值爲'0',但從不將類型引用爲'Nothing'。 – Ryan 2011-05-25 02:53:44

+1

儘管我還不想初始化爲Nothing,但他可能會這樣做,以避免在賦值「變量」myItem之前使用「變量myItem」的警告。在運行時可能會產生空引用異常。如果你沒有,你會得到。這個警告最糟糕的部分是,我要麼通過初始化爲無效(並仍然「冒險」空引用exc)來抑制它,要麼就像'如果myItem IsNot Nothing Then ...' – 2011-05-25 04:22:34

0

沒有看到更多的代碼,我會建議在我的Case語句上使用Enumeration以防止出現小錯誤。您可以使用Factory Method來基於枚舉來處理數據。

相關問題