2011-05-24 21 views
5

Heredé un código y me causa vergüenza cuando lo miro. ¿Hay una forma más elegante de escribir lo siguiente?¿Hay alguna manera elegante de escribir este código?

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 

¿Hay alguna manera de hacer un mapa de la cadena para el tipo de clase y luego solo tiene una línea como esa? ¿O algo similar?

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

Respuesta

1

Dado que BusManager es un genérico, el tipo que pase a Of <type> debe especificarse en el momento de la compilación. No es como un parámetro tradicional que puede cambiar en tiempo de ejecución.

No está claro en el código que aparece lo que BusManager realmente hace. Si todo lo que hace es crear una instancia del tipo Genérico, entonces tal vez la persona que lo creó realmente no entienda los genéricos. ¿Tiene la capacidad de volver a trabajar cómo funciona el BusManager, o está limitado a usarlo tal cual?

Como se menciona en @jmoreno, puede usar la reflexión para crear una instancia de un tipo a partir de una cadena que contenga el nombre del tipo. Aquí es cómo funcionaría:

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 

En una aplicación de producción, lo que probablemente establezca el tipo de cambio de todos estos métodos a mi clase base o interfaz. Solo asegúrese de pasar el typeName completo incluyendo el espacio de nombres.

Con esa clase de fábrica en su lugar, a continuación, la versión elegante de su código sería algo como esto:

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

Wow se ve bien, ¡muchas gracias! –

0

En primer lugar, nunca use Case Is = y nunca inicializar a Nothing. Por lo tanto una rápida sería:

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

Pero ya que estás usando plantillas, no hay realmente ninguna manera de hacer un mapa a menos que desee utilizar la reflexión, que es terriblemente ineficientes a expensas de código un poco más limpio y más corto. También puede agregar un Imports DTO para guardar en 124 caracteres, y también Bus para guardar en otros 120 caracteres.

+1

¿sería capaz de dar más detalles sobre no usar 'caso es =' y nunca se inicializa a 'Nada ¿? Soy relativamente nuevo en VB. –

+0

'Case Is = xxx' es directamente equivalente a' Case xxx', por lo que no tiene sentido, solo agrega ruido sintáctico. Inicializar los tipos de referencia a 'Nothing' tampoco tiene sentido porque eso es lo que son de forma predeterminada. A veces puede ser más claro inicializar los valores 'Boolean' a' False' y los valores numéricos a '0' pero nunca los tipos de referencia a' Nothing'. – Ryan

+1

Aunque también prefiero no inicializar a 'Nothing', probablemente lo haga para evitar la advertencia de que" Variable 'myItem' se usa antes de que se le haya asignado un valor. Una excepción de referencia nula podría resultar en el tiempo de ejecución. " que obtienes si no lo haces La peor parte de esta advertencia es que o la suprimo al inicializar a nada (y sigo "arriesgando" null ref exc) o recibo la advertencia en una línea como 'Si myItem IsNot Nothing Then ...' –

0

Sin ver más código, recomendaría usar un Enumeration en mi extracto de cuenta para evitar que aparezcan errores menores.

Puede utilizar Factory Method para procesar los datos según la enumeración.

Cuestiones relacionadas