Ejemplo
Supongamos la siguiente enumeración:
''' <summary> ''' Sitio donde se escribe el fichero log ''' </summary> <FlagsAttribute()> _ Public Enum DondeEscriboLogE ''' <summary>Valor None</summary> None = 0 ''' <summary>Un fichero de texto estandard</summary> FicheroTxt = 1 ''' <summary>Un fichero XML</summary> FicheroXml = 2 ''' <summary>En una pagina Html</summary> FicheroHtml = 4 ''' <summary>Un fichero con formato CSV</summary> FicheroCsv = 8 ''' <summary>En el registro de eventos de Windows</summary> RegistroEventos = 16 End Enum
La enumeración [ DondeEscriboLogE ] está marcada con el atributo [FlagsAttribute] lo quiere decir que se permiten opciones múltiples, por ejemplo
Dim lugarDondeEscribo As DondeEscriboLogE = DondeEscriboLogE.FicheroTxt Or DondeEscriboLogE.FicheroXml Or DondeEscriboLogE.RegistroEventos
El problema es diseñar un código que ejecute las diversas opciones cando la opción es múltiple,
La solución es (relativamente) fácil
En primer lugar observa que el siguiente código carga en el [Array] [Values], los valores numéricos de la enumeración, es decir, 1,2,4,8,16
'Array que contiene los valores numericos de la enumeracion (1,2,4,8,16, etc) Dim values As Array = [Enum].GetValues(GetType(DondeEscriboLogE))
[ lugarDondeEscribo ] es la constante enumerada elegida por el usuario ( en este cso tiene un valor multiple)
[ ValorEnumCargadaUser ] es el valor numérico de la enumeración elegida por el usuario, como es multi opción puede tener un valor intermedio .Por ejemplo 18, por ejemplo 3 que corresponde a una opción múltiple [1+2] o por ejemplo 19 [1+2+16]
Dim ValorEnumCargadaUser As Integer = CType(lugarDondeEscribo, Integer)
El proceso a seguir es el siguiente.
Supongamos que el número de la constante enumerada elegida es 19 (recuerda que los valores numéricos de la enumeración son: 1, 2, 4, 8, 16)
Paso 1) 19>= 16 --> Si ( 16 es una opción a ejecutar) resto 19-16 = 3
Paso 2) 3>= 8 -> No
Paso 3) 3>= 4 -> No
Paso 4) 3>= 2 -> Si ( 2 es una opción a ejecutar) resto 3-2 = 1
Paso 5) 1>= 1 -> Si ( 1 es una opción a ejecutar) resto 1-1 = 0
Paso 6) Valor 0 --> fin del proceso
Observa que se recorren los valores del mayor al menor
Dim ValorEnumeracion As Integer ' iteración de la colección [Values] ( valores numéricos de la enumeración) ' se recorre en orden inverso, empezando por la ultima hasta la primera For indice As Integer = values.GetUpperBound(0) To values.GetLowerBound(0) Step -1 ' obtener el valor de la enumeracion ( por ejemplo 16) ValorEnumeracion = CType(values.GetValue(indice), Integer) 'Proceso ' vuelta 1) 19 > = 16 -> Si ( 16 es una opción a ejecutar) resto 19 - 16 = 3 ' vuelta 2) 3 > = 8 -> No ' vuelta 3) 3 > = 4 -> No ' vuelta 4) 3 > = 2 -> Si ( 2 es una opción a ejecutar) resto 3 - 2 = 1 ' vuelta 5) 1 > = 1 -> Si ( 1 es una opción a ejecutar) resto 1 - 1 = 0 ' vuelta 6) Valor 0 -> fin del proceso ' Observa que se recorren los valores del mayor al menor If ValorEnumCargadaUser > = ValorEnumeracion Then ' HAY que ejecutar la opción de la enumeración cuyo ' valor numérico es [ValorEnumeracion] ' La interfaz Dim objInterfaz As ITraceLog ' el valor de la enumeracion que se va a ejecutar Dim localConstanteEnumerada As DondeEscriboLogE = CType(ValorEnumeracion, DondeEscriboLogE) ' cargar la interfaz con el objeto adecuado objInterfaz = BuscaInterfaz(localConstanteEnumerada) ' ' = = = = = = = = = = = = = = = = = = = = = = = = = ' aquí ejecutar la operación objInterfaz.WriteException(ex, type, additionalInfo) ' ‘restar el valor para seguir iterando ValorEnumCargadaUser = ValorEnumCargadaUser - ValorEnumeracion End If Next
La función [] es relativamente sencilla, en función del valor de la constante enumerada devuelve una interfaz cargada con su clase correspondiente.
Private Function BuscaInterfaz(ByVal plugarDondeEscribo As DondeEscriboLogE) As ITraceLog Dim objInterfaz As ITraceLog Select Case plugarDondeEscribo Case DondeEscriboLogE.None objInterfaz = New TracelogNull Case DondeEscriboLogE.FicheroTxt objInterfaz = New TraceLogToFile Case DondeEscriboLogE.FicheroXml objInterfaz = New TraceLogToXmlWriter Case DondeEscriboLogE.FicheroHtml objInterfaz = New TracelogNull Case DondeEscriboLogE.FicheroCsv objInterfaz = New TracelogNull Case DondeEscriboLogE.RegistroEventos objInterfaz = New TracelogNull Case Else Throw New NotImplementedException End Select Return objInterfaz End Function
La clase [ TraceLogToFile ] tiene una función [] que se encarga de añadir al fichero log del disco el valor que queremos escribir
Para evitar problemas, he diseñao la clase [ TracelogNull ] que sigue el Patron Null Object , y que tiene el siguiente formato
''' <summary> ''' Clase traceLog patron Noting ''' </summary> ''' <remarks></remarks> Public Class TracelogNull Implements IDisposable, ITraceLog ''' <summary> ''' Constructor general ''' </summary> Public Sub New() ' End Sub Public Overloads Sub WriteEntry(ByVal message As String) Implements ITraceLog.WriteEntry End Sub Public Overloads Sub WriteEntry(ByVal message As String, ByVal type As TraceEventType) Implements ITraceLog.WriteEntry End Sub Public Overloads Sub WriteException(ByVal ex As Exception) Implements ITraceLog.WriteException End Sub Public Overloads Sub WriteException(ByVal ex As Exception, ByVal additionalInfo As String) Implements ITraceLog.WriteException End Sub Public Overloads Sub WriteException(ByVal ex As Exception, ByVal type As TraceEventType) Implements ITraceLog.WriteException End Sub Public Overloads Sub WriteException(ByVal ex As Exception, ByVal type As TraceEventType, ByVal additionalInfo As String) Implements ITraceLog.WriteException End Sub ' Visual Basic agregó este código para implementar correctamente el patrón descartable. Public Sub Dispose() Implements IDisposable.Dispose GC.SuppressFinalize(Me) End Sub End Class