2011-11-30 20 views
11

che ho una classe con un numero qualsiasi di proprietà di qualsiasi tipoAggiunta di attributi aggiuntivi per ogni proprietà di una classe

public class Test 
{ 
public string A {get;set;} 
public object B {get;set;} 
public int C {get;set;} 
public CustomClass D {get;set;} 
} 

Voglio che tutti gli oggetti all'interno di questa classe ad avere una nozione di 'errori' e 'avvertimenti'. Ad esempio, in base ad alcune condizioni in un'altra classe, potrei voler impostare un avviso sulla proprietà A e quindi visualizzare tali informazioni nella GUI. La GUI non è la mia preoccupazione; piuttosto come dovrei impostare questo avviso? Mi piacerebbe essere in grado di fare qualcosa di simile:

Per ogni proprietà in una classe, aggiungere un 'Warning' e 'Errore' proprietà tale che posso fare ..

Test t = new Test(); 
t.A.Warning = "This is a warning that the GUI will know to display in yellow". 
t.B.Error = null; 

Qual è la migliore modo di fare questo? Sarebbe bello se potessi aggiungere un attributo personalizzato a ciascuna proprietà della classe che aggiungesse queste proprietà aggiuntive e mi permettesse di accedervi in ​​modo chiaro.

Ho visto soluzioni che aggiungono un dizionario alla classe genitore (Test), e quindi passano stringhe che corrispondono ai nomi di proprietà, o usano reflection per ottenere il nome della proprietà e passarlo, ma preferirei qualcosa di più pulito .

risposta

8

Si potrebbe aggiungere un attributo personalizzato che si desidera la proprietà e quindi utilizzare un metodo di estensione sull'oggetto per accedere a tali attributi.

Qualcosa del genere dovrebbe funzionare

In primo luogo è necessario creare la classe attributo

[AttributeUsage(AttributeTargets.All/*, AllowMultiple = true*/)] 
public class WarningAttribute : System.attribute 
{ 
    public readonly string Warning; 

    public WarningAttribute(string warning) 
    { 
     this.Warning = warning; 
    }  
} 

Più Reading Here

usarlo come tale

[WarningAttribute("Warning String")] 
public string A {get;set;} 

Poi accedervi come così MSDN Article

public static string Warning(this Object object) 
{ 
    System.Attribute[] attrs = System.Attribute.GetCustomAttributes(object); 

    foreach (System.Attribute attr in attrs) 
     { 
      if (attr is WarningAttrbiute) 
      { 
       return (WarningAttribute)attr.Warning; 
      } 
     } 
} 

Poi, se si dispone di un elemento che si desidera accedere l'avvertimento su di voi può semplicemente chiamare

test.A.Warning; 

Se hai intenzione di impostare la stringa di avviso si potrebbe implementare un qualche tipo di setter per questo un po 'più pulito. Potenzialmente attraverso l'impostazione di un oggetto secondario o di un tipo di proprietà.


Un metodo alternativo per fare questo sarebbe invece di utilizzare string e object si potrebbe creare un tipo generico personalizzato per gestire tale impostazione di proprietà.

Qualcosa di simile

public class ValidationType<T> 
{ 
    public T Value {get; set;} 
    public string Warning {get; set;} 
    public string Error {get; set;} 

    public ValidationType(T value) 
    { 
     Value = value; 
    } 
} 

Usa come

var newWarning = new ValidationType<string>("Test Type"); 
newWarning.Warning = "Test STring"; 
Console.WriteLine("newWarning.Value"); 

+0

Grazie per la risposta. Penso che implementerò questo. Non mi piace dover usare newWarning.Value per accedere effettivamente alle proprietà della stringa, ma sembra che dovrò sacrificare qualche comodità da qualche parte. – user981225

1

In primo luogo, gli attributi non possono modificare l'oggetto su cui sono posizionati. A meno che non li combini con AOP. Suggerirei di utilizzare una classe wrapper attorno alla classe ereditandola, a condizione che le classi non siano sigillate. Se sono sigillati, dovrai scrivere una classe wrapper vera e propria, passando tutte le operazioni, tranne quelle che aggiungi, a un campo privato che è un'istanza della classe del tuo wrapping.

Modifica: Per facilità d'uso, l'approccio al metodo di estensione suggerito è probabilmente la soluzione migliore.

2

Se si riuscisse a ottenere un metodo anziché una proprietà, si potrebbe creare un'estensione per l'oggetto, ma sarebbe difficile restringere l'utilizzo solo per alcune classi.

Qualcosa di simile:

public static void Warning(this object target, string message) 
{ 
... 
} 

public static String GetWarning(this object target) 
{ 
} 

Naturalmente sarebbe difficile mantenere un tale avvertimento in stato dell'oggetto, ma poi si potrebbe utilizzare alcuni dizionari, ecc

+0

Grazie per il tuo post ma preferirei evitare questa soluzione. Voglio che la proprietà effettiva sappia se ha o meno un errore, non che l'oggetto genitore debba scorrere un dizionario di stringhe (per esempio). – user981225

2

Piuttosto che cercare di attribuire le proprietà, vorrei suggerire di aggiungere un insieme di proprietà di errore/avvertimento per una classe base che il vostro gli oggetti aziendali ereditano da.

In questo modo, è possibile fornire informazioni più dettagliate, è possibile rimuoverle quando sono state visualizzate all'utente e, se si inviano i dati su "il filo" (servizi Web, servizi wcf), il gli errori possono viaggiare con i tuoi oggetti invece di richiedere un'elaborazione speciale per inviare gli attributi.

Problemi correlati