Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Eleкtro en 23 Septiembre 2014, 21:49 pm



Título: ¿Alternativa al atributo RangeAttribute de ASP.NET?
Publicado por: Eleкtro en 23 Septiembre 2014, 21:49 pm
¿Alguien conoce alguna alternativa al > RangeAttribute (http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.rangeattribute%28v=vs.110%29.aspx) <, para WindowsForms?, me parece que .Net Framework no expone nada parecido más que para ASP.Net, pero no estoy seguro de ello.

Leí acerca de como implementar este atributo usando la librería > PostSharp (http://doc.postsharp.net/t_postsharp_patterns_contracts_rangeattribute) <, es muy sencillo implementarlo de forma básica la verdad, pero es un producto de pago y la "medicina" no funciona muy bien, de todas formas muestro un ejemplo por si a alguien le sirve:

Código
  1. ''' <summary>
  2. ''' Specifies the numeric range constraints for the value of a data field.
  3. ''' </summary>
  4. <Serializable>
  5. Class RangeAttribute : Inherits PostSharp.Aspects.LocationInterceptionAspect
  6.  
  7.    ''' <summary>
  8.    ''' The minimum range value.
  9.    ''' </summary>
  10.    Private min As Integer
  11.  
  12.    ''' <summary>
  13.    ''' The maximum range value.
  14.    ''' </summary>
  15.    Private max As Integer
  16.  
  17.    ''' <summary>
  18.    ''' Initializes a new instance of the <see cref="RangeAttribute" /> class.
  19.    ''' </summary>
  20.    ''' <param name="min">The minimum range value.</param>
  21.    ''' <param name="max">The maximum range value.</param>
  22.    Public Sub New(ByVal min As Integer, ByVal max As Integer)
  23.  
  24.        Me.min = min
  25.        Me.max = max
  26.  
  27.    End Sub
  28.  
  29.    ''' <summary>
  30.    ''' Method invoked <i>instead</i> of the <c>Set</c> semantic of the field or property to which the current aspect is applied,
  31.    ''' i.e. when the value of this field or property is changed.
  32.    ''' </summary>
  33.    ''' <param name="args">Advice arguments.</param>
  34.    Public Overrides Sub OnSetValue(ByVal args As PostSharp.Aspects.LocationInterceptionArgs)
  35.  
  36.        Dim value As Integer = CInt(args.Value)
  37.  
  38.        If value < min Then
  39.            value = min
  40.  
  41.        ElseIf value > max Then
  42.            value = max
  43.  
  44.        End If
  45.  
  46.        args.SetNewValue(value)
  47.  
  48.    End Sub
  49.  
  50. End Class

En fin, si hay que implementarlo por uno mismo sin la ayuda de herramientas de terceros pues se implementa desde cero, pero ni siquiera conozco que Class debería heredar para empezar a crear un atributo de metadatos parecido al RangeAttribute, que funcione en WinForms, apenas puedo encontrar información sobre esto en Google/MSDN y todo lo que encuentro es para ASP.Net.

PD: Actualmente hago la validación del rango en el getter/setter de las propiedades, así que eso no contaría como "alternativa" xD.

Cualquier información se agradece,
Saludos!


Título: Re: ¿Alternativa al atributo RangeAttribute de ASP.NET?
Publicado por: Novlucker en 4 Octubre 2014, 19:12 pm
http://msdn.microsoft.com/en-us/library/ms950965.aspx :P

Saludos


Título: Re: ¿Alternativa al atributo RangeAttribute de ASP.NET?
Publicado por: Eleкtro en 4 Octubre 2014, 20:31 pm
Vaya, me alegra verte por aqui de nuevo NovLucker, y muchas gracias por la documentación, aunque no he sacado practicamente nada en claro.

Mi intención es transformar esto:

Código
  1. Public Class MyType
  2.  
  3. ''' <summary>
  4. ''' Gets or sets the value.
  5. ''' </summary>
  6. ''' <value>The value.</value>
  7. Public Property MyProperty As Integer
  8.    Get
  9.        Return Me._MyValue
  10.    End Get
  11.    Set(ByVal value As Integer)
  12.  
  13.        If value < Me._MyValueMin Then
  14.            If Me._MyValueThrowRangeException Then
  15.                Throw New ArgumentOutOfRangeException("MyValue", Me._MyValueExceptionMessage)
  16.            End If
  17.            Me._MyValue = Me._MyValueMin
  18.  
  19.        ElseIf value > Me._MyValueMax Then
  20.            If Me._MyValueThrowRangeException Then
  21.                Throw New ArgumentOutOfRangeException("MyValue", Me._MyValueExceptionMessage)
  22.            End If
  23.            Me._MyValue = Me._MyValueMax
  24.  
  25.        Else
  26.            Me._MyValue = value
  27.  
  28.        End If
  29.  
  30.    End Set
  31. End Property
  32. Private _MyValue As Integer = 0I
  33. Private _MyValueMin As Integer = 0I
  34. Private _MyValueMax As Integer = 10I
  35. Private _MyValueThrowRangeException As Boolean = True
  36. Private _MyValueExceptionMessage As String = String.Format("The valid range is beetwen {0} and {1}",
  37.                                                           Me._MyValueMin, Me._MyValueMax)
  38.  
  39. End Class


En algo más simplificado, y sobre todo rehusable, como esto:

Código
  1. Public NotInheritable Class MyType
  2.  
  3.    ''' <summary>
  4.    ''' Gets or sets the value.
  5.    ''' Valid range is between 0 and 10.
  6.    ''' </summary>
  7.    ''' <value>The value.</value>
  8.    <RangeAttribute(0, 10, ThrowRangeException:=False, ExceptionMessage:="")>
  9.    Public Property MyProperty As Integer
  10.  
  11. End Class


Pero no soy capaz de descubrir o entender como puedo hookear el getter/setter, apenas tengo información sobre ello, de todas formas intenté empezar a hacerlo y esto es lo que tengo, un código que no sirve para nada, porque no estoy evaluando nada, pero al menos sirve como idea inicial:

Código
  1. <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)>
  2. Public Class RangeAttribute : Inherits Attribute
  3.  
  4.    ''' <summary>
  5.    ''' Indicates the Minimum range value.
  6.    ''' </summary>
  7.    Public Minimum As Single
  8.  
  9.    ''' <summary>
  10.    ''' Indicates the Maximum range value.
  11.    ''' </summary>
  12.    Public Maximum As Single
  13.  
  14.    ''' <summary>
  15.    ''' Determines whether to throw an exception when the value is not in range.
  16.    ''' </summary>
  17.    Public ThrowRangeException As Boolean
  18.  
  19.    ''' <summary>
  20.    ''' Indicates the exception message to show when the value is not in range.
  21.    ''' </summary>
  22.    Public ExceptionMessage As String
  23.  
  24.    ''' <summary>
  25.    ''' Initializes a new instance of the <see cref="RangeAttribute"/> class.
  26.    ''' </summary>
  27.    ''' <param name="Minimum">The minimum range value.</param>
  28.    ''' <param name="Maximum">The maximum range value.</param>
  29.    Public Sub New(ByVal Minimum As Single,
  30.                   ByVal Maximum As Single)
  31.  
  32.        Me.New(Minimum, Maximum, ThrowRangeException:=False, ExceptionMessage:=String.Empty)
  33.  
  34.    End Sub
  35.  
  36.    ''' <summary>
  37.    ''' Initializes a new instance of the <see cref="RangeAttribute"/> class.
  38.    ''' </summary>
  39.    ''' <param name="Minimum">The minimum range value.</param>
  40.    ''' <param name="Maximum">The maximum range value.</param>
  41.    ''' <param name="ThrowRangeException">
  42.    ''' Determines whether to throw an exception when the value is not in range.
  43.    ''' </param>
  44.    Public Sub New(ByVal Minimum As Single,
  45.                   ByVal Maximum As Single,
  46.                   ByVal ThrowRangeException As Boolean,
  47.                   Optional ByVal ExceptionMessage As String = "")
  48.  
  49.        Me.Minimum = Minimum
  50.        Me.Maximum = Maximum
  51.        Me.ThrowRangeException = ThrowRangeException
  52.  
  53.        If Not String.IsNullOrEmpty(ExceptionMessage) Then
  54.            Me.ExceptionMessage = ExceptionMessage
  55.        Else
  56.            Me.ExceptionMessage = String.Format("The valid range is beetwen {0} and {1}", Minimum, Maximum)
  57.        End If
  58.  
  59.    End Sub
  60.  
  61. End Class

Cualquier información adicional se agradece.

Un saludo!