2011-02-06 7 views
1

Je travaille sur un projet où j'ai besoin de mettre en file d'attente un certain nombre de changements de propriétés. Disons que je:Paramètre de propriété différée C#

public class foo 
{ 
    string bar { get; set; } 
    int bar1 { get; set } 
} 

Je veux avoir un code qui ressemble à:

//Store value set actions in a queue 
foo.SetValue(bar, "abc"); 
foo.SetValue(bar1, 123); 

//Preview changes 
foreach(Item change in foo.ChangeQueue) 
{ 
    Console.Write(change.PropertyName.ToString()); 
    Console.Write(change.Value.ToString()); 
} 

//Apply actions 
foo.CommitChanges(); 

Quelle est la meilleure façon d'y parvenir?

+0

Vous ne vous souciez donc que du paramètre le plus récent ou devez-vous mettre en file d'attente toutes les modifications apportées à une propriété particulière? – Gabe

+0

Toutes les modifications – Matt

Répondre

1

"typées" qui utilise la version callbacks. Cela ne supprimera pas automatiquement les paramètres en double. Il n'utilise pas non plus de réflexion et donc les erreurs de nom de propriété échoueront lors de la compilation. Cette méthode pourrait être élargie pour exiger un "nom" et supprimer les doublons en utilisant un dictionnaire (selon la réponse d'Akash) ou permettre au "setter" de renvoyer une valeur (comme le succès ou l'échec ou l'ancienne valeur, ou autre).

interface Setter { 
    void Apply(); 
} 
class Setter<T> : Setter { 
    public T Data; 
    public Action<T> SetFn; 
    public void Apply() { 
     SetFn(Data); 
    } 
} 

List<Setter> changeQueue = new List<Setter>(); 

void SetValue<T>(Action<T> setFn, T data){ 
    changeQueue.Add(new Setter<T> { 
     Data = data, 
     SetFn = setFn, 
    }); 
} 

void ApplyChanges(){ 
    foreach (var s in changeQueue){ 
     s.Apply(); 
    } 
} 

// .. later on 
SetValue(x => System.Console.WriteLine(x), "hello world!"); 
ApplyChanges(); 

Cette méthode peut également être utilisé trivialement « en dehors » les objets surveillés parce que toutes les opérations sont des fermetures potentielles.

Bonne codification.

+0

Pouvez-vous élaborer sur: SetValue (x => System.Console.WriteLine (x), "hello world!"); ? Je ne pourrais pas obtenir ceci pour fonctionner immédiatement, je dois manquer quelque chose. – Matt

+0

'SetValue' (est en fait mal nommé) - il faut une action à effectuer plus tard (quand ApplyChanges est appelé) Dans ce cas, je viens d'écrire des effets secondaires sur la console - un exemple réel: SetValue (x => myObject.IntProperty = x, 10) '(notez qu'il * capture * l'objet cible sur lequel la valeur sera définie dans une fermeture). Le type de 'x' est le type de la valeur transmise (string dans mon code, int dans l'exemple dans le commentaire) et est déduit de' T' dans la définition de la méthode (les deux T doivent être identiques donc C# faites-en correspondre). –

+0

@Matt Si cette méthode fait partie d'une classe, il est également possible, de manière sécurisée, de passer la classe en cours à l'action (ajouter un second paramètre de type à Setter '), par ex. avec quelques re-working: 'myObject.SetValue ((x, o) => o.Property = x, ...)' qui évite la fermeture (où o est monObjet, mais avec un nom différent). –

2

Vous pouvez utiliser Dictionary<string,object> comme ChangeQueue pour stocker vos valeurs.

Vous pouvez itérer que,

foreach(KeyValuePair<string,object> item in ChangeQueue){ 
    Console.WriteLine(item.Key);// name of property 
    Console.WriteLine(item.Value); // value of property 
} 


public void SetValue(string name, object value){ 
    PropertyInfo p = this.GetType().GetProperty(name); 

    // following convert and raise an exception to preserve type safety 
    ChangeQueue[name] = Convert.ChangeType(value,p.PropertyType); 
} 

public void ApplyChanges(){ 
    foreach(KeyValuePair<string,object> item in ChangeQueue){ 
     PropertyInfo p = this.GetType().GetProperty(item.Key); 
     p.SetValue(this, item.Value, null); 
    } 
} 
+1

Et si toutes les modifications doivent être suivies ou si l'ordre de modification est important, 'IEnumerable >' est un remplacement presque direct du dictionnaire ci-dessus. –

+0

Cela semble ok. Mais, il n'y a pas de sécurité de type. – Matt

+0

J'ai mis à jour mon code pour introduire la sécurité de type –