2016-05-11 4 views
1

J'ai une classe générique avec un seul argument qui représente un élément d'une DLL tierce dans le but de sérialiser des objets de type T. Ce que je voudrais faire, c'est ajouter une carte 'sale' à ma classe et la déclencher paresseusement chaque fois que l'une des propriétés imbriquées de mon élément est modifiée.C# sur le suivi des modifications de propriétés imbriquées

Est-il possible lorsque la propriété est accédée d'attraper la demande et d'identifier quelle propriété change? Que si un SET est en cours, je peux enregistrer cette sous-propriété P est maintenant sale et doit être sauvegardé? Ou au moins un seul bit qui indique que quelque chose a changé?

public class ResourceSerializer<T> 
    where T : Base, new() 
    { 
    T element; 
    Dictionary<String,Boolean> dirtyMap; 

    public T Element { get { return this.getElement(); } } 
    public Boolean IsDirty { get; private set; } 

    public ResourceSerializer() 
    { 
    dirtyMap = new Dictionary<string,bool>(); 
    element = new T(); 
    // code to reflect back upon T's Properties and build out the dirtyMap. 
    // I already can do this I just omitted it. 
    // in my Person example there would be keys: 'FirstName', 'LastName', 'Age', 'Gender', 'PrimaryAddress' 
    } 


    // how can I call this programmatically? 
    void flagDirty(String property) 
    { 
    dirtyMap[property] = true; 
    this.IsDirty = true; 
    } 
    T getElement() 
    { 
    // In case I need to do a thing before returning the element. 
    // Not relevant to the question at hand. 
    return this.element; 
    } 
} 

un exemple un peu avancé de 'Base'. Vous pouvez voir comment j'ai besoin de recréer mes actions car tout n'est pas primitif. J'ai une classe de niveau de gestionnaire qui enregistre tous ces objets ResourceSerializer.

public class Base 
{ 
    public Base() 
    { 

    } 
} 
public enum gender 
{ 
    Male, 
    Female, 
    Other, 
    Unspecified, 
} 
    public class Address : Base 
{ 
    public String Street { get; set; } 
    public String State { get; set; } 
    public String Zip { get; set; } 
    public Address() : base() 
    { 

    } 
} 
public class Person : Base 
{ 
    public String FirstName { get; set; } 
    public String LastName { get; set; } 
    public Int16 Age { get; set; } 
    public gender Gender { get; set; } 
    public Address PrimaryAddress { get; set; } 
    public Person() : base() 
    { 

    } 
} 
public class Patient : Person 
{ 
    public Person PrimaryContact { get; set; } 
    public Patient() : base() 
    { 

    } 
} 

et une petite classe i se transformerait en une méthode d'essai plus tard ..

public class DoThing 
    { 
    public DoThing() 
    { 
     ResourceSerializer<Person> person = new ResourceSerializer<Person>(); 
     person.Element.Age = 13; // catch this and mark 'Age' as dirty. 
    } 
    } 

Répondre

0

Sans un poseur de mesure non, il n'y a rien à faire. Le modèle habituel pour ce que vous essayez de faire est d'implémenter l'interface INotifyPropertyChanged, cette interface est créée précisément pour les classes (ou structures) qui ont besoin de suivre et d'informer sur les changements sur leurs propriétés. Si vous êtes paresseux comme moi, je créerais un analyseur qui au début de mon application balaye toutes mes classes qui sont marquées avec un attribut et avec toutes les propriétés créées comme virtuelles, puis en utilisant codedom je voudrais créer un nouveau class qui hériterait de la classe found et implémente l'INotifyPropertyChanged, alors vous pouvez avoir une Factory générique qui retourne des instances de ces nouvelles classes lorsque le type de l'appel générique est d'un type enregistré connu. Je l'ai déjà utilisé pour les classes que je voulais avoir des propriétés à distance, juste étiqueté la classe et mon système de scan a réécrit le getter/setter pour faire les appels à distance de manière transparente, le concept à la fin est le même.

Il y a beaucoup de travail au début, mais si vous avez une tonne de classes, il y aura beaucoup moins de code à écrire que l'implémentation de INotifyPropertyChanged sur toutes vos classes.

+0

Oui, la DLL que je référence a des centaines de classes et aucune de leurs propriétés sont virales. J'espérais accomplir de manière réfléchie tout cela. – user3562367

+0

Ensuite, votre meilleur pari est de créer un système comme celui que j'ai décrit, recréer les types de classe dynamiquement avec codedom. – Gusman

+0

Whops, n'a pas lu sur le bit virtuel ... si c'est votre cas alors peut-être en utilisant le mot-clé 'new' vous pouvez le faire, n'oubliez pas de lire et d'écrire à la propriété de base. – Gusman