2010-05-19 18 views
14

que desea crear un atributo personalizado que puede ser utilizado en una propiedad como:¿Cómo obtener y modificar un valor de propiedad a través de un atributo personalizado?

[TrimInputString] 
public string FirstName { get; set; } 

que será equivalente funcional de

private string _firstName 
public string FirstName { 
    set { 
    _firstName = value.Trim(); 
    } 
    get { 
    return _firstName; 
    } 
} 

Así que, básicamente, todas las propiedades de tiempo se ajusta el valor se va a recortar .

¿Cómo calculo el valor, modifico ese valor y luego establezco la propiedad con el nuevo valor todo dentro del atributo?

[AttributeUsage(AttributeTargets.Property)] 
public class TrimInputAttribute : Attribute { 

    public TrimInputAttribute() { 
    //not sure how to get and modify the property here 
    } 

} 
+0

Creo que un mejor enfoque es un DataBinder: http://stackoverflow.com/a/1734025/7720 – Romias

Respuesta

6

Así no funcionan los atributos. No puede acceder a cualquier atributo al que esté adjunto desde el constructor.

Si desea hacer esto, tendrá que hacer algún tipo de clase de procesador al que pase el objeto, que luego recorre los campos y hace algo dependiendo de los atributos. La operación a realizar se puede definir dentro del atributo (un atributo base abstracto es útil aquí), pero igual tendrá que recorrer los campos a mano para aplicar la operación.

1

Como señaló Matti, así no es cómo funcionan los atributos. Sin embargo, puede usar PostSharp AOP framework para lograr esto, probablemente anulando OnMethodBoundaryAspect. Pero esto no es trivial.

7

iam haciendo esto, no de manera muy convincente, pero su trabajo

clase de demostración

public class User 
{ 

[TitleCase] 
public string FirstName { get; set; } 

[TitleCase] 
public string LastName { get; set; } 

[UpperCase] 
public string Salutation { get; set; } 

[LowerCase] 
public string Email { get; set; } 

} 

escritura Atributo de minúsculas, otros pueden ser escritos de manera similar

public class LowerCaseAttribute : ValidationAttribute 
{ 
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     //try to modify text 
      try 
      { 
       validationContext 
       .ObjectType 
       .GetProperty(validationContext.MemberName) 
       .SetValue(validationContext.ObjectInstance, value.ToString().ToLower(), null); 
      } 
      catch (System.Exception) 
      {          
      } 

     //return null to make sure this attribute never say iam invalid 
     return null; 
    } 
} 

Manera no muy elegante ya que en realidad está implementando el atributo Validación b ut funciona

+0

Esto, por supuesto, solo funciona si su programa en algún momento ejecuta la validación de los objetos. Interesante truco, pero no lo usaría en el código de producción. –

+1

Quizás desee 'devolver ValidationResult.Success;' – Nikola

0

Esto se puede hacer con Dado.ComponentModel.Mutations.

public class User 
{ 
    [Trim] 
    public string FirstName { get; set; } 
} 

// Then to preform mutation 
var user = new User() { 
    FirstName = " David Glenn " 
} 

new MutationContext<User>(user).Mutate(); 

Se puede ver más documentación here.

+0

No juzgando sobre la solución en sí. Pero el espacio de nombres elegido me parece engañoso. Mi primera impresión es que es parte del propio framework .Net. Mientras que no lo es. Por qué no iniciar el espacio de nombres con RoyDukkey.ComponentModel.Mutations y dar crédito a su nombre también. –

+0

Estoy de acuerdo. Esto fue originalmente creado como una propuesta, pero desde entonces ha sido cerrado. Todavía tengo tiempo para cambiar el espacio de nombres a algo más apropiado. – roydukkey

Cuestiones relacionadas