我继承了一些代码,当我看到它时,它让我感到畏缩。是否有更优雅的方式来写下面的内容?
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()
答案 0 :(得分:1)
由于BusManager
是Generic,因此必须在编译时指定传递给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())
答案 1 :(得分: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个字符。
答案 2 :(得分:0)
如果没有看到更多代码,我建议在我的Case语句中使用Enumeration来防止出现小错误。
然后,您可以使用Factory Method根据枚举处理数据。